OAuth Provider Rewrite (#182)
This commit is contained in:
357
passbook/providers/oauth2/migrations/0001_initial.py
Normal file
357
passbook/providers/oauth2/migrations/0001_initial.py
Normal file
@ -0,0 +1,357 @@
|
||||
# Generated by Django 3.1 on 2020-08-18 15:59
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.apps.registry import Apps
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
|
||||
|
||||
import passbook.core.models
|
||||
import passbook.lib.utils.time
|
||||
import passbook.providers.oauth2.generators
|
||||
|
||||
SCOPE_OPENID_EXPRESSION = """# This is only required for OpenID Applications, but does not grant any information by itself.
|
||||
return {}
|
||||
"""
|
||||
SCOPE_EMAIL_EXPRESSION = """return {
|
||||
"email": user.email,
|
||||
"email_verified": True
|
||||
}
|
||||
"""
|
||||
SCOPE_PROFILE_EXPRESSION = """return {
|
||||
"name": user.name,
|
||||
"given_name": user.name,
|
||||
"family_name": "",
|
||||
"preferred_username": user.username,
|
||||
"nickname": user.username,
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
def create_default_scopes(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
|
||||
ScopeMapping = apps.get_model("passbook_providers_oauth2", "ScopeMapping")
|
||||
ScopeMapping.objects.update_or_create(
|
||||
scope_name="openid",
|
||||
defaults={
|
||||
"name": "Autogenerated OAuth2 Mapping: OpenID 'openid'",
|
||||
"scope_name": "openid",
|
||||
"description": "",
|
||||
"expression": SCOPE_OPENID_EXPRESSION,
|
||||
},
|
||||
)
|
||||
ScopeMapping.objects.update_or_create(
|
||||
scope_name="email",
|
||||
defaults={
|
||||
"name": "Autogenerated OAuth2 Mapping: OpenID 'email'",
|
||||
"scope_name": "email",
|
||||
"description": "Email address",
|
||||
"expression": SCOPE_EMAIL_EXPRESSION,
|
||||
},
|
||||
)
|
||||
ScopeMapping.objects.update_or_create(
|
||||
scope_name="profile",
|
||||
defaults={
|
||||
"name": "Autogenerated OAuth2 Mapping: OpenID 'profile'",
|
||||
"scope_name": "profile",
|
||||
"description": "General Profile Information",
|
||||
"expression": SCOPE_PROFILE_EXPRESSION,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
("passbook_core", "0007_auto_20200815_1841"),
|
||||
("passbook_crypto", "0002_create_self_signed_kp"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunSQL(
|
||||
"DROP TABLE IF EXISTS passbook_providers_oauth_oauth2provider CASCADE;"
|
||||
),
|
||||
migrations.RunSQL(
|
||||
"DROP TABLE IF EXISTS passbook_providers_oidc_openidprovider CASCADE;"
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="OAuth2Provider",
|
||||
fields=[
|
||||
(
|
||||
"provider_ptr",
|
||||
models.OneToOneField(
|
||||
auto_created=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
parent_link=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
to="passbook_core.provider",
|
||||
),
|
||||
),
|
||||
("name", models.TextField()),
|
||||
(
|
||||
"client_type",
|
||||
models.CharField(
|
||||
choices=[
|
||||
("confidential", "Confidential"),
|
||||
("public", "Public"),
|
||||
],
|
||||
default="confidential",
|
||||
help_text="<b>Confidential</b> clients are capable of maintaining the confidentiality\n of their credentials. <b>Public</b> clients are incapable.",
|
||||
max_length=30,
|
||||
verbose_name="Client Type",
|
||||
),
|
||||
),
|
||||
(
|
||||
"client_id",
|
||||
models.CharField(
|
||||
default=passbook.providers.oauth2.generators.generate_client_id,
|
||||
max_length=255,
|
||||
unique=True,
|
||||
verbose_name="Client ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"client_secret",
|
||||
models.CharField(
|
||||
blank=True,
|
||||
default=passbook.providers.oauth2.generators.generate_client_secret,
|
||||
max_length=255,
|
||||
verbose_name="Client Secret",
|
||||
),
|
||||
),
|
||||
(
|
||||
"response_type",
|
||||
models.TextField(
|
||||
choices=[
|
||||
("code", "code (Authorization Code Flow)"),
|
||||
("id_token", "id_token (Implicit Flow)"),
|
||||
("id_token token", "id_token token (Implicit Flow)"),
|
||||
("code token", "code token (Hybrid Flow)"),
|
||||
("code id_token", "code id_token (Hybrid Flow)"),
|
||||
(
|
||||
"code id_token token",
|
||||
"code id_token token (Hybrid Flow)",
|
||||
),
|
||||
],
|
||||
default="code",
|
||||
help_text="Response Type required by the client.",
|
||||
),
|
||||
),
|
||||
(
|
||||
"jwt_alg",
|
||||
models.CharField(
|
||||
choices=[
|
||||
("HS256", "HS256 (Symmetric Encryption)"),
|
||||
("RS256", "RS256 (Asymmetric Encryption)"),
|
||||
],
|
||||
default="RS256",
|
||||
help_text="Algorithm used to sign the JWT Token",
|
||||
max_length=10,
|
||||
verbose_name="JWT Algorithm",
|
||||
),
|
||||
),
|
||||
(
|
||||
"redirect_uris",
|
||||
models.TextField(
|
||||
default="",
|
||||
help_text="Enter each URI on a new line.",
|
||||
verbose_name="Redirect URIs",
|
||||
),
|
||||
),
|
||||
(
|
||||
"post_logout_redirect_uris",
|
||||
models.TextField(
|
||||
blank=True,
|
||||
default="",
|
||||
help_text="Enter each URI on a new line.",
|
||||
verbose_name="Post Logout Redirect URIs",
|
||||
),
|
||||
),
|
||||
(
|
||||
"include_claims_in_id_token",
|
||||
models.BooleanField(
|
||||
default=True,
|
||||
help_text="Include User claims from scopes in the id_token, for applications that don't access the userinfo endpoint.",
|
||||
verbose_name="Include claims in id_token",
|
||||
),
|
||||
),
|
||||
(
|
||||
"token_validity",
|
||||
models.TextField(
|
||||
default="minutes=10",
|
||||
help_text="Tokens not valid on or after current time + this value (Format: hours=1;minutes=2;seconds=3).",
|
||||
validators=[passbook.lib.utils.time.timedelta_string_validator],
|
||||
),
|
||||
),
|
||||
(
|
||||
"rsa_key",
|
||||
models.ForeignKey(
|
||||
help_text="Key used to sign the tokens. Only required when JWT Algorithm is set to RS256.",
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to="passbook_crypto.certificatekeypair",
|
||||
verbose_name="RSA Key",
|
||||
blank=True,
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "OAuth2/OpenID Provider",
|
||||
"verbose_name_plural": "OAuth2/OpenID Providers",
|
||||
},
|
||||
bases=("passbook_core.provider",),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="ScopeMapping",
|
||||
fields=[
|
||||
(
|
||||
"propertymapping_ptr",
|
||||
models.OneToOneField(
|
||||
auto_created=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
parent_link=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
to="passbook_core.propertymapping",
|
||||
),
|
||||
),
|
||||
("scope_name", models.TextField(help_text="Scope used by the client")),
|
||||
(
|
||||
"description",
|
||||
models.TextField(
|
||||
blank=True,
|
||||
help_text="Description shown to the user when consenting. If left empty, the user won't be informed.",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "Scope Mapping",
|
||||
"verbose_name_plural": "Scope Mappings",
|
||||
},
|
||||
bases=("passbook_core.propertymapping",),
|
||||
),
|
||||
migrations.RunPython(create_default_scopes),
|
||||
migrations.CreateModel(
|
||||
name="RefreshToken",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"expires",
|
||||
models.DateTimeField(
|
||||
default=passbook.core.models.default_token_duration
|
||||
),
|
||||
),
|
||||
("expiring", models.BooleanField(default=True)),
|
||||
("_scope", models.TextField(default="", verbose_name="Scopes")),
|
||||
(
|
||||
"access_token",
|
||||
models.CharField(
|
||||
max_length=255, unique=True, verbose_name="Access Token"
|
||||
),
|
||||
),
|
||||
(
|
||||
"refresh_token",
|
||||
models.CharField(
|
||||
max_length=255, unique=True, verbose_name="Refresh Token"
|
||||
),
|
||||
),
|
||||
("_id_token", models.TextField(verbose_name="ID Token")),
|
||||
(
|
||||
"provider",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to="passbook_providers_oauth2.oauth2provider",
|
||||
),
|
||||
),
|
||||
(
|
||||
"user",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
verbose_name="User",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={"verbose_name": "Token", "verbose_name_plural": "Tokens",},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="AuthorizationCode",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"expires",
|
||||
models.DateTimeField(
|
||||
default=passbook.core.models.default_token_duration
|
||||
),
|
||||
),
|
||||
("expiring", models.BooleanField(default=True)),
|
||||
("_scope", models.TextField(default="", verbose_name="Scopes")),
|
||||
(
|
||||
"code",
|
||||
models.CharField(max_length=255, unique=True, verbose_name="Code"),
|
||||
),
|
||||
(
|
||||
"nonce",
|
||||
models.CharField(
|
||||
blank=True, default="", max_length=255, verbose_name="Nonce"
|
||||
),
|
||||
),
|
||||
(
|
||||
"is_open_id",
|
||||
models.BooleanField(
|
||||
default=False, verbose_name="Is Authentication?"
|
||||
),
|
||||
),
|
||||
(
|
||||
"code_challenge",
|
||||
models.CharField(
|
||||
max_length=255, null=True, verbose_name="Code Challenge"
|
||||
),
|
||||
),
|
||||
(
|
||||
"code_challenge_method",
|
||||
models.CharField(
|
||||
max_length=255, null=True, verbose_name="Code Challenge Method"
|
||||
),
|
||||
),
|
||||
(
|
||||
"provider",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to="passbook_providers_oauth2.oauth2provider",
|
||||
),
|
||||
),
|
||||
(
|
||||
"user",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
verbose_name="User",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "Authorization Code",
|
||||
"verbose_name_plural": "Authorization Codes",
|
||||
},
|
||||
),
|
||||
]
|
||||
0
passbook/providers/oauth2/migrations/__init__.py
Normal file
0
passbook/providers/oauth2/migrations/__init__.py
Normal file
Reference in New Issue
Block a user