Keycloak realm with groups (#2002)

* added a group and mapper to keycloak w/ burnettk

* accept an internal uri to keycloak w/ burnettk

* pyl w/ burnettk

* the only time we ever use internal arg to open_id_endpoint_for_name we want it True

* protect users of openid urls from internal urls

* allow port 8000/8001 for docker and avoid public urls when using requests again

* allow 8001 frontend in docker compose post logout redirect url

---------

Co-authored-by: jasquat <jasquat@users.noreply.github.com>
Co-authored-by: burnettk <burnettk@users.noreply.github.com>
This commit is contained in:
jasquat 2024-07-29 10:39:50 -04:00 committed by GitHub
parent b8c7aa991d
commit d2c5c27bdc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 129 additions and 106 deletions

View File

@ -30,7 +30,7 @@ on:
push: push:
branches: branches:
- main - main
- spiffui/newui - keycloak-realm-with-groups
tags: [v*] tags: [v*]
jobs: jobs:

View File

@ -1,17 +1,20 @@
#!/usr/bin/env bash #!/usr/bin/env bash
function error_handler() { function error_handler() {
>&2 echo "Exited with BAD EXIT CODE '${2}' in ${0} script at line: ${1}." echo >&2 "Exited with BAD EXIT CODE '${2}' in ${0} script at line: ${1}."
exit "$2" exit "$2"
} }
trap 'error_handler ${LINENO} $?' ERR trap 'error_handler ${LINENO} $?' ERR
set -o errtrace -o errexit -o nounset -o pipefail set -o errtrace -o errexit -o nounset -o pipefail
script_dir="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" script_dir="$(
cd -- "$(dirname "$0")" >/dev/null 2>&1
pwd -P
)"
realms="$*" realms="$*"
if [[ -z "$realms" ]]; then if [[ -z "$realms" ]]; then
realms="spiffworkflow-realm" realms="spiffworkflow-local-realm"
fi fi
docker_container_path=/tmp/hey docker_container_path=/tmp/hey
@ -20,8 +23,8 @@ docker exec keycloak rm -rf "$docker_container_path"
docker exec keycloak /opt/keycloak/bin/kc.sh export --dir "${docker_container_path}" --users realm_file || echo '' docker exec keycloak /opt/keycloak/bin/kc.sh export --dir "${docker_container_path}" --users realm_file || echo ''
docker cp "keycloak:${docker_container_path}" "$local_tmp_dir" docker cp "keycloak:${docker_container_path}" "$local_tmp_dir"
for realm in $realms ; do for realm in $realms; do
if ! grep -Eq '\-realm$' <<< "$realm"; then if ! grep -Eq '\-realm$' <<<"$realm"; then
realm="${realm}-realm" realm="${realm}-realm"
fi fi
cp "${local_tmp_dir}/hey/${realm}.json" "${script_dir}/../realm_exports/" cp "${local_tmp_dir}/hey/${realm}.json" "${script_dir}/../realm_exports/"

View File

@ -441,7 +441,17 @@
] ]
} }
}, },
"groups": [], "groups": [
{
"id": "a14e6081-ffd4-4925-9364-4916bcf74931",
"name": "group_keycloak",
"path": "/group_keycloak",
"attributes": {},
"realmRoles": [],
"clientRoles": {},
"subGroups": []
}
],
"defaultRole": { "defaultRole": {
"id": "c9f0ff93-642d-402b-965a-04d70719886b", "id": "c9f0ff93-642d-402b-965a-04d70719886b",
"name": "default-roles-spiffworkflow", "name": "default-roles-spiffworkflow",
@ -458,7 +468,11 @@
"otpPolicyLookAheadWindow": 1, "otpPolicyLookAheadWindow": 1,
"otpPolicyPeriod": 30, "otpPolicyPeriod": 30,
"otpPolicyCodeReusable": false, "otpPolicyCodeReusable": false,
"otpSupportedApplications": ["totpAppFreeOTPName", "totpAppGoogleName"], "otpSupportedApplications": [
"totpAppMicrosoftAuthenticatorName",
"totpAppFreeOTPName",
"totpAppGoogleName"
],
"webAuthnPolicyRpEntityName": "keycloak", "webAuthnPolicyRpEntityName": "keycloak",
"webAuthnPolicySignatureAlgorithms": ["ES256"], "webAuthnPolicySignatureAlgorithms": ["ES256"],
"webAuthnPolicyRpId": "", "webAuthnPolicyRpId": "",
@ -493,7 +507,7 @@
"id": "644ff652-31d1-4349-9340-ce3b5fb76b5c", "id": "644ff652-31d1-4349-9340-ce3b5fb76b5c",
"type": "password", "type": "password",
"createdDate": 1676302139645, "createdDate": 1676302139645,
"secretData": "{\"value\":\"P6nrEJgmgdL+HbNA9tPkOyHYaLAqLg6cXh27ACgVQiOox4qwNE8Iv1L4ssispV4gsmuHiY+alio/2UMuyMGvEw==\",\"salt\":\"g214ckcAyig59U/3Oqwq4w==\",\"additionalParameters\":{}}", "secretData": "{\"value\":\"nhHncfQqkY1vhJE8QxjD3hwpznBnZNc5+OxS79OFKJc=\",\"salt\":\"EradsPFeRiQ3oMAzGqfWBw==\",\"additionalParameters\":{}}",
"credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}"
} }
], ],
@ -504,7 +518,7 @@
"realm-management": ["realm-admin"] "realm-management": ["realm-admin"]
}, },
"notBefore": 0, "notBefore": 0,
"groups": [] "groups": ["/group_keycloak"]
}, },
{ {
"id": "4c436296-8471-4105-b551-80eee96b43bb", "id": "4c436296-8471-4105-b551-80eee96b43bb",
@ -651,6 +665,42 @@
"realmRoles": ["default-roles-spiffworkflow"], "realmRoles": ["default-roles-spiffworkflow"],
"notBefore": 0, "notBefore": 0,
"groups": [] "groups": []
},
{
"id": "d2a86264-e3ca-4a82-99b8-0a6cd714ded4",
"createdTimestamp": 1722019421345,
"username": "service-account-spiffworkflow-backend",
"enabled": true,
"totp": false,
"emailVerified": false,
"serviceAccountClientId": "spiffworkflow-backend",
"credentials": [],
"disableableCredentialTypes": [],
"requiredActions": [],
"realmRoles": ["default-roles-spiffworkflow"],
"clientRoles": {
"spiffworkflow-backend": ["uma_protection"]
},
"notBefore": 0,
"groups": []
},
{
"id": "bae51d14-9d82-468f-9e9d-1cd2cb507f15",
"createdTimestamp": 1722019421396,
"username": "service-account-withauth",
"enabled": true,
"totp": false,
"emailVerified": false,
"serviceAccountClientId": "withAuth",
"credentials": [],
"disableableCredentialTypes": [],
"requiredActions": [],
"realmRoles": ["default-roles-spiffworkflow"],
"clientRoles": {
"withAuth": ["uma_protection"]
},
"notBefore": 0,
"groups": []
} }
], ],
"scopeMappings": [ "scopeMappings": [
@ -1031,9 +1081,8 @@
"secret": "JXeQExm0JhQPLumgHtIIqf52bDalHz0q", "secret": "JXeQExm0JhQPLumgHtIIqf52bDalHz0q",
"redirectUris": [ "redirectUris": [
"http://localhost:7000/*", "http://localhost:7000/*",
"https://replace-me-with-spiff-backend-host-and-path/*", "http://localhost:8000/*",
"http://67.205.133.116:7000/*", "https://for-local-dev.spiffworkflow.org/*"
"http://167.172.242.138:7000/*"
], ],
"webOrigins": [], "webOrigins": [],
"notBefore": 0, "notBefore": 0,
@ -1051,7 +1100,7 @@
"saml.force.post.binding": "false", "saml.force.post.binding": "false",
"saml.multivalued.roles": "false", "saml.multivalued.roles": "false",
"frontchannel.logout.session.required": "false", "frontchannel.logout.session.required": "false",
"post.logout.redirect.uris": "https://replace-me-with-spiff-frontend-host-and-path/*##http://localhost:7001/*", "post.logout.redirect.uris": "https://replace-me-with-spiff-frontend-host-and-path/*##http://localhost:7001/*##http://localhost:8001/*",
"oauth2.device.authorization.grant.enabled": "false", "oauth2.device.authorization.grant.enabled": "false",
"backchannel.logout.revoke.offline.tokens": "false", "backchannel.logout.revoke.offline.tokens": "false",
"saml.server.signature.keyinfo.ext": "false", "saml.server.signature.keyinfo.ext": "false",
@ -1320,9 +1369,7 @@
"redirectUris": [ "redirectUris": [
"https://api.unused-for-local-dev.spiffworkflow.org/*", "https://api.unused-for-local-dev.spiffworkflow.org/*",
"http://localhost:7001/*", "http://localhost:7001/*",
"http://67.205.133.116:7000/*", "http://localhost:8001/*"
"http://167.172.242.138:7001/*",
"https://api.demo.spiffworkflow.org/*"
], ],
"webOrigins": ["*"], "webOrigins": ["*"],
"notBefore": 0, "notBefore": 0,
@ -1391,10 +1438,7 @@
"secret": "6o8kIKQznQtejHOdRhWeKorBJclMGcgA", "secret": "6o8kIKQznQtejHOdRhWeKorBJclMGcgA",
"redirectUris": [ "redirectUris": [
"https://api.unused-for-local-dev.spiffworkflow.org/*", "https://api.unused-for-local-dev.spiffworkflow.org/*",
"http://localhost:7001/*", "http://localhost:8001/*"
"http://67.205.133.116:7000/*",
"http://167.172.242.138:7001/*",
"https://api.demo.spiffworkflow.org/*"
], ],
"webOrigins": [], "webOrigins": [],
"notBefore": 0, "notBefore": 0,
@ -1712,6 +1756,20 @@
"jsonType.label": "String" "jsonType.label": "String"
} }
}, },
{
"id": "75c10b23-3a63-4aa6-99cc-7c8b7645d32f",
"name": "groups",
"protocol": "openid-connect",
"protocolMapper": "oidc-group-membership-mapper",
"consentRequired": false,
"config": {
"full.path": "true",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "groups",
"userinfo.token.claim": "true"
}
},
{ {
"id": "b05e679c-e00e-427e-8e47-0a4fd411c7a6", "id": "b05e679c-e00e-427e-8e47-0a4fd411c7a6",
"name": "updated at", "name": "updated at",
@ -2071,6 +2129,7 @@
"browserSecurityHeaders": { "browserSecurityHeaders": {
"contentSecurityPolicyReportOnly": "", "contentSecurityPolicyReportOnly": "",
"xContentTypeOptions": "nosniff", "xContentTypeOptions": "nosniff",
"referrerPolicy": "no-referrer",
"xRobotsTag": "none", "xRobotsTag": "none",
"xFrameOptions": "SAMEORIGIN", "xFrameOptions": "SAMEORIGIN",
"contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';",
@ -2106,14 +2165,14 @@
"subComponents": {}, "subComponents": {},
"config": { "config": {
"allowed-protocol-mapper-types": [ "allowed-protocol-mapper-types": [
"saml-user-attribute-mapper",
"oidc-sha256-pairwise-sub-mapper", "oidc-sha256-pairwise-sub-mapper",
"oidc-usermodel-attribute-mapper",
"saml-user-property-mapper",
"saml-role-list-mapper",
"oidc-address-mapper", "oidc-address-mapper",
"oidc-full-name-mapper", "oidc-full-name-mapper",
"saml-user-attribute-mapper", "oidc-usermodel-property-mapper"
"oidc-usermodel-property-mapper",
"saml-role-list-mapper",
"saml-user-property-mapper",
"oidc-usermodel-attribute-mapper"
] ]
} }
}, },
@ -2135,14 +2194,14 @@
"subComponents": {}, "subComponents": {},
"config": { "config": {
"allowed-protocol-mapper-types": [ "allowed-protocol-mapper-types": [
"oidc-full-name-mapper",
"saml-user-property-mapper",
"oidc-usermodel-property-mapper",
"saml-role-list-mapper",
"oidc-address-mapper", "oidc-address-mapper",
"saml-user-property-mapper",
"oidc-full-name-mapper",
"saml-user-attribute-mapper", "saml-user-attribute-mapper",
"oidc-usermodel-attribute-mapper",
"saml-role-list-mapper",
"oidc-sha256-pairwise-sub-mapper", "oidc-sha256-pairwise-sub-mapper",
"oidc-usermodel-attribute-mapper" "oidc-usermodel-property-mapper"
] ]
} }
}, },
@ -2281,40 +2340,6 @@
} }
] ]
}, },
{
"id": "7675760b-666a-4b8c-a9b8-da1e01c207fe",
"alias": "Authentication Options",
"description": "Authentication options.",
"providerId": "basic-flow",
"topLevel": false,
"builtIn": true,
"authenticationExecutions": [
{
"authenticator": "basic-auth",
"authenticatorFlow": false,
"requirement": "REQUIRED",
"priority": 10,
"autheticatorFlow": false,
"userSetupAllowed": false
},
{
"authenticator": "basic-auth-otp",
"authenticatorFlow": false,
"requirement": "DISABLED",
"priority": 20,
"autheticatorFlow": false,
"userSetupAllowed": false
},
{
"authenticator": "auth-spnego",
"authenticatorFlow": false,
"requirement": "DISABLED",
"priority": 30,
"autheticatorFlow": false,
"userSetupAllowed": false
}
]
},
{ {
"id": "34e18ea8-f515-46dc-9dbf-5b79f8154564", "id": "34e18ea8-f515-46dc-9dbf-5b79f8154564",
"alias": "Browser - Conditional OTP", "alias": "Browser - Conditional OTP",
@ -2687,32 +2712,6 @@
} }
] ]
}, },
{
"id": "70ef5a26-e3bb-4ba7-a05a-d205b0a3836c",
"alias": "http challenge",
"description": "An authentication flow based on challenge-response HTTP Authentication Schemes",
"providerId": "basic-flow",
"topLevel": true,
"builtIn": true,
"authenticationExecutions": [
{
"authenticator": "no-cookie-redirect",
"authenticatorFlow": false,
"requirement": "REQUIRED",
"priority": 10,
"autheticatorFlow": false,
"userSetupAllowed": false
},
{
"authenticatorFlow": true,
"requirement": "REQUIRED",
"priority": 20,
"autheticatorFlow": true,
"flowAlias": "Authentication Options",
"userSetupAllowed": false
}
]
},
{ {
"id": "89abf09a-bfb4-4dea-b164-ca7c563b4009", "id": "89abf09a-bfb4-4dea-b164-ca7c563b4009",
"alias": "registration", "alias": "registration",
@ -2862,9 +2861,9 @@
"config": {} "config": {}
}, },
{ {
"alias": "terms_and_conditions", "alias": "TERMS_AND_CONDITIONS",
"name": "Terms and Conditions", "name": "Terms and Conditions",
"providerId": "terms_and_conditions", "providerId": "TERMS_AND_CONDITIONS",
"enabled": false, "enabled": false,
"defaultAction": false, "defaultAction": false,
"priority": 20, "priority": 20,
@ -2940,7 +2939,7 @@
"parRequestUriLifespan": "60", "parRequestUriLifespan": "60",
"clientSessionMaxLifespan": "0" "clientSessionMaxLifespan": "0"
}, },
"keycloakVersion": "20.0.1", "keycloakVersion": "22.0.4",
"userManagedAccessAllowed": false, "userManagedAccessAllowed": false,
"clientProfiles": { "clientProfiles": {
"profiles": [] "profiles": []

View File

@ -241,12 +241,13 @@ def setup_config(app: Flask) -> None:
if app.config.get("SPIFFWORKFLOW_BACKEND_AUTH_CONFIGS") is None: if app.config.get("SPIFFWORKFLOW_BACKEND_AUTH_CONFIGS") is None:
app.config["SPIFFWORKFLOW_BACKEND_AUTH_CONFIGS"] = [ app.config["SPIFFWORKFLOW_BACKEND_AUTH_CONFIGS"] = [
{ {
"identifier": "default", "additional_valid_client_ids": app.config.get("SPIFFWORKFLOW_BACKEND_OPEN_ID_ADDITIONAL_VALID_CLIENT_IDS"),
"label": "Default",
"uri": app.config.get("SPIFFWORKFLOW_BACKEND_OPEN_ID_SERVER_URL"),
"client_id": app.config.get("SPIFFWORKFLOW_BACKEND_OPEN_ID_CLIENT_ID"), "client_id": app.config.get("SPIFFWORKFLOW_BACKEND_OPEN_ID_CLIENT_ID"),
"client_secret": app.config.get("SPIFFWORKFLOW_BACKEND_OPEN_ID_CLIENT_SECRET_KEY"), "client_secret": app.config.get("SPIFFWORKFLOW_BACKEND_OPEN_ID_CLIENT_SECRET_KEY"),
"additional_valid_client_ids": app.config.get("SPIFFWORKFLOW_BACKEND_OPEN_ID_ADDITIONAL_VALID_CLIENT_IDS"), "identifier": "default",
"internal_uri": app.config.get("SPIFFWORKFLOW_BACKEND_OPEN_ID_SERVER_INTERNAL_URL"),
"label": "Default",
"uri": app.config.get("SPIFFWORKFLOW_BACKEND_OPEN_ID_SERVER_URL"),
} }
] ]

View File

@ -134,6 +134,7 @@ else:
SPIFFWORKFLOW_BACKEND_OPEN_ID_SERVER_URL = url_config SPIFFWORKFLOW_BACKEND_OPEN_ID_SERVER_URL = url_config
config_from_env("SPIFFWORKFLOW_BACKEND_OPEN_ID_CLIENT_ID", default="spiffworkflow-backend") config_from_env("SPIFFWORKFLOW_BACKEND_OPEN_ID_CLIENT_ID", default="spiffworkflow-backend")
config_from_env("SPIFFWORKFLOW_BACKEND_OPEN_ID_CLIENT_SECRET_KEY", default="JXeQExm0JhQPLumgHtIIqf52bDalHz0q") config_from_env("SPIFFWORKFLOW_BACKEND_OPEN_ID_CLIENT_SECRET_KEY", default="JXeQExm0JhQPLumgHtIIqf52bDalHz0q")
config_from_env("SPIFFWORKFLOW_BACKEND_OPEN_ID_SERVER_INTERNAL_URL")
# comma-separated list of client ids that can be successfully validated against. # comma-separated list of client ids that can be successfully validated against.
# useful for api users that will login to a different client on the same realm but from something external to backend. # useful for api users that will login to a different client on the same realm but from something external to backend.
@ -148,6 +149,7 @@ else:
{ {
"identifier": "default", "identifier": "default",
"label": "Default", "label": "Default",
"internal_uri": "http://localhost:7002/realms/spiffworkflow-local",
"uri": "http://localhost:7002/realms/spiffworkflow-local", "uri": "http://localhost:7002/realms/spiffworkflow-local",
"client_id": "spiffworkflow-backend", "client_id": "spiffworkflow-backend",
"client_secret": "JXeQExm0JhQPLumgHtIIqf52bDalHz0q", "client_secret": "JXeQExm0JhQPLumgHtIIqf52bDalHz0q",

View File

@ -72,6 +72,7 @@ class AuthenticationProviderTypes(enum.Enum):
class AuthenticationOptionForApi(TypedDict): class AuthenticationOptionForApi(TypedDict):
identifier: str identifier: str
label: str label: str
internal_uri: NotRequired[str]
uri: str uri: str
additional_valid_client_ids: NotRequired[str] additional_valid_client_ids: NotRequired[str]
@ -122,9 +123,14 @@ class AuthenticationService:
return [cls.client_id(authentication_identifier), "account"] return [cls.client_id(authentication_identifier), "account"]
@classmethod @classmethod
def server_url(cls, authentication_identifier: str) -> str: def server_url(cls, authentication_identifier: str, internal: bool = False) -> str:
"""Returns the server url from the config.""" """Returns the server url from the config."""
config: str = cls.authentication_option_for_identifier(authentication_identifier)["uri"] auth_config = cls.authentication_option_for_identifier(authentication_identifier)
uri_key = "uri"
if internal:
if "internal_uri" in auth_config and auth_config["internal_uri"] is not None:
uri_key = "internal_uri"
config: str = auth_config[uri_key] # type: ignore
return config return config
@classmethod @classmethod
@ -134,15 +140,16 @@ class AuthenticationService:
return config return config
@classmethod @classmethod
def open_id_endpoint_for_name(cls, name: str, authentication_identifier: str) -> str: def open_id_endpoint_for_name(cls, name: str, authentication_identifier: str, internal: bool = False) -> str:
"""All openid systems provide a mapping of static names to the full path of that endpoint.""" """All openid systems provide a mapping of static names to the full path of that endpoint."""
appropriate_server_url = cls.server_url(authentication_identifier)
openid_config_url = f"{appropriate_server_url}/.well-known/openid-configuration"
if authentication_identifier not in cls.ENDPOINT_CACHE: if authentication_identifier not in cls.ENDPOINT_CACHE:
cls.ENDPOINT_CACHE[authentication_identifier] = {} cls.ENDPOINT_CACHE[authentication_identifier] = {}
if authentication_identifier not in cls.JSON_WEB_KEYSET_CACHE: if authentication_identifier not in cls.JSON_WEB_KEYSET_CACHE:
cls.JSON_WEB_KEYSET_CACHE[authentication_identifier] = {} cls.JSON_WEB_KEYSET_CACHE[authentication_identifier] = {}
internal_server_url = cls.server_url(authentication_identifier, internal=True)
openid_config_url = f"{internal_server_url}/.well-known/openid-configuration"
if name not in AuthenticationService.ENDPOINT_CACHE[authentication_identifier]: if name not in AuthenticationService.ENDPOINT_CACHE[authentication_identifier]:
try: try:
response = safe_requests.get(openid_config_url, timeout=HTTP_REQUEST_TIMEOUT_SECONDS) response = safe_requests.get(openid_config_url, timeout=HTTP_REQUEST_TIMEOUT_SECONDS)
@ -151,7 +158,14 @@ class AuthenticationService:
raise OpenIdConnectionError(f"Cannot connect to given open id url: {openid_config_url}") from ce raise OpenIdConnectionError(f"Cannot connect to given open id url: {openid_config_url}") from ce
if name not in AuthenticationService.ENDPOINT_CACHE[authentication_identifier]: if name not in AuthenticationService.ENDPOINT_CACHE[authentication_identifier]:
raise Exception(f"Unknown OpenID Endpoint: {name}. Tried to get from {openid_config_url}") raise Exception(f"Unknown OpenID Endpoint: {name}. Tried to get from {openid_config_url}")
config: str = AuthenticationService.ENDPOINT_CACHE[authentication_identifier].get(name, "") config: str = AuthenticationService.ENDPOINT_CACHE[authentication_identifier].get(name, "")
external_server_url = cls.server_url(authentication_identifier)
if internal is False:
if internal_server_url != external_server_url:
config = config.replace(internal_server_url, external_server_url)
return config return config
@classmethod @classmethod
@ -166,7 +180,7 @@ class AuthenticationService:
@classmethod @classmethod
def jwks_public_key_for_key_id(cls, authentication_identifier: str, key_id: str) -> JWKSKeyConfig: def jwks_public_key_for_key_id(cls, authentication_identifier: str, key_id: str) -> JWKSKeyConfig:
jwks_uri = cls.open_id_endpoint_for_name("jwks_uri", authentication_identifier) jwks_uri = cls.open_id_endpoint_for_name("jwks_uri", authentication_identifier, internal=True)
jwks_configs = cls.get_jwks_config_from_uri(jwks_uri) jwks_configs = cls.get_jwks_config_from_uri(jwks_uri)
json_key_configs: JWKSKeyConfig | None = cls.get_key_config(jwks_configs, key_id) json_key_configs: JWKSKeyConfig | None = cls.get_key_config(jwks_configs, key_id)
if not json_key_configs: if not json_key_configs:
@ -303,7 +317,9 @@ class AuthenticationService:
"redirect_uri": f"{self.get_backend_url()}{redirect_url}", "redirect_uri": f"{self.get_backend_url()}{redirect_url}",
} }
request_url = self.open_id_endpoint_for_name("token_endpoint", authentication_identifier=authentication_identifier) request_url = self.open_id_endpoint_for_name(
"token_endpoint", authentication_identifier=authentication_identifier, internal=True
)
response = requests.post(request_url, data=data, headers=headers, timeout=HTTP_REQUEST_TIMEOUT_SECONDS) response = requests.post(request_url, data=data, headers=headers, timeout=HTTP_REQUEST_TIMEOUT_SECONDS)
auth_token_object: dict = json.loads(response.text) auth_token_object: dict = json.loads(response.text)
@ -432,7 +448,9 @@ class AuthenticationService:
"client_secret": cls.secret_key(authentication_identifier), "client_secret": cls.secret_key(authentication_identifier),
} }
request_url = cls.open_id_endpoint_for_name("token_endpoint", authentication_identifier=authentication_identifier) request_url = cls.open_id_endpoint_for_name(
"token_endpoint", authentication_identifier=authentication_identifier, internal=True
)
response = requests.post(request_url, data=data, headers=headers, timeout=HTTP_REQUEST_TIMEOUT_SECONDS) response = requests.post(request_url, data=data, headers=headers, timeout=HTTP_REQUEST_TIMEOUT_SECONDS)
auth_token_object: dict = json.loads(response.text) auth_token_object: dict = json.loads(response.text)