providers/oauth2: allow m2m for JWKS without alg in keys (#12196)
* providers/oauth2: allow m2m for JWKS without alg in keys Signed-off-by: Jens Langhammer <jens@goauthentik.io> * Update index.md Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com> Signed-off-by: Jens L. <jens@beryju.org> * Apply suggestions from code review Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com> Signed-off-by: Jens L. <jens@beryju.org> --------- Signed-off-by: Jens Langhammer <jens@goauthentik.io> Signed-off-by: Jens L. <jens@beryju.org> Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
This commit is contained in:
@ -393,19 +393,22 @@ class TokenParams:
|
|||||||
LOGGER.warning("failed to parse JWT for kid lookup", exc=exc)
|
LOGGER.warning("failed to parse JWT for kid lookup", exc=exc)
|
||||||
raise TokenError("invalid_grant") from None
|
raise TokenError("invalid_grant") from None
|
||||||
expected_kid = decode_unvalidated["header"]["kid"]
|
expected_kid = decode_unvalidated["header"]["kid"]
|
||||||
|
fallback_alg = decode_unvalidated["header"]["alg"]
|
||||||
for source in self.provider.jwks_sources.filter(
|
for source in self.provider.jwks_sources.filter(
|
||||||
oidc_jwks__keys__contains=[{"kid": expected_kid}]
|
oidc_jwks__keys__contains=[{"kid": expected_kid}]
|
||||||
):
|
):
|
||||||
LOGGER.debug("verifying JWT with source", source=source.slug)
|
LOGGER.debug("verifying JWT with source", source=source.slug)
|
||||||
keys = source.oidc_jwks.get("keys", [])
|
keys = source.oidc_jwks.get("keys", [])
|
||||||
for key in keys:
|
for key in keys:
|
||||||
|
if key.get("kid") and key.get("kid") != expected_kid:
|
||||||
|
continue
|
||||||
LOGGER.debug("verifying JWT with key", source=source.slug, key=key.get("kid"))
|
LOGGER.debug("verifying JWT with key", source=source.slug, key=key.get("kid"))
|
||||||
try:
|
try:
|
||||||
parsed_key = PyJWK.from_dict(key)
|
parsed_key = PyJWK.from_dict(key)
|
||||||
token = decode(
|
token = decode(
|
||||||
assertion,
|
assertion,
|
||||||
parsed_key.key,
|
parsed_key.key,
|
||||||
algorithms=[key.get("alg")],
|
algorithms=[key.get("alg")] if "alg" in key else [fallback_alg],
|
||||||
options={
|
options={
|
||||||
"verify_aud": False,
|
"verify_aud": False,
|
||||||
},
|
},
|
||||||
|
@ -10,7 +10,7 @@ Hence identification is based on service-accounts, and authentication is based o
|
|||||||
|
|
||||||
An example request can look like this:
|
An example request can look like this:
|
||||||
|
|
||||||
```
|
```http
|
||||||
POST /application/o/token/ HTTP/1.1
|
POST /application/o/token/ HTTP/1.1
|
||||||
Host: authentik.company
|
Host: authentik.company
|
||||||
Content-Type: application/x-www-form-urlencoded
|
Content-Type: application/x-www-form-urlencoded
|
||||||
@ -42,7 +42,7 @@ Starting with authentik 2022.6, you can define a JWKS URL/raw JWKS data in OAuth
|
|||||||
|
|
||||||
With this configure, any JWT issued by the configured certificates can be used to authenticate:
|
With this configure, any JWT issued by the configured certificates can be used to authenticate:
|
||||||
|
|
||||||
```
|
```http
|
||||||
POST /application/o/token/ HTTP/1.1
|
POST /application/o/token/ HTTP/1.1
|
||||||
Host: authentik.company
|
Host: authentik.company
|
||||||
Content-Type: application/x-www-form-urlencoded
|
Content-Type: application/x-www-form-urlencoded
|
||||||
|
@ -14,7 +14,7 @@ authentik doesn't ship with a default flow for this usecase, so it is recommende
|
|||||||
|
|
||||||
The flow is initiated by sending a POST request to the device authorization endpoint, `/application/o/device/` with the following contents:
|
The flow is initiated by sending a POST request to the device authorization endpoint, `/application/o/device/` with the following contents:
|
||||||
|
|
||||||
```
|
```http
|
||||||
POST /application/o/device/ HTTP/1.1
|
POST /application/o/device/ HTTP/1.1
|
||||||
Host: authentik.company
|
Host: authentik.company
|
||||||
Content-Type: application/x-www-form-urlencoded
|
Content-Type: application/x-www-form-urlencoded
|
||||||
@ -36,7 +36,7 @@ The response contains the following fields:
|
|||||||
|
|
||||||
With this response, the device can start checking the status of the token by sending requests to the token endpoint like this:
|
With this response, the device can start checking the status of the token by sending requests to the token endpoint like this:
|
||||||
|
|
||||||
```
|
```http
|
||||||
POST /application/o/token/ HTTP/1.1
|
POST /application/o/token/ HTTP/1.1
|
||||||
Host: authentik.company
|
Host: authentik.company
|
||||||
Content-Type: application/x-www-form-urlencoded
|
Content-Type: application/x-www-form-urlencoded
|
||||||
|
@ -111,3 +111,22 @@ return True
|
|||||||
9. Open **Flow settings** and choose _azure-ad-enrollment_ as enrollment flow.
|
9. Open **Flow settings** and choose _azure-ad-enrollment_ as enrollment flow.
|
||||||
|
|
||||||
Try to login with a **_new_** user. You should see no prompts and the user should have the correct information.
|
Try to login with a **_new_** user. You should see no prompts and the user should have the correct information.
|
||||||
|
|
||||||
|
### Machine-to-machine authentication <span class="badge badge--version">authentik 2024.12+</span>
|
||||||
|
|
||||||
|
If using [Machine-to-Machine](../../../../add-secure-apps/providers/oauth2/client_credentials.md#jwt-authentication) authentication, some specific steps need to be considered.
|
||||||
|
|
||||||
|
When getting the JWT token from Azure AD, set the scope to the Application ID URI, and _not_ the Graph URL; otherwise the JWT will be in an invalid format.
|
||||||
|
|
||||||
|
```http
|
||||||
|
POST /<azure-ad-tenant-id>/oauth2/v2.0/token/ HTTP/1.1
|
||||||
|
Host: login.microsoftonline.com
|
||||||
|
Content-Type: application/x-www-form-urlencoded
|
||||||
|
|
||||||
|
grant_type=client_credentials&
|
||||||
|
client_id=<application_client_id>&
|
||||||
|
scope=api://<application_client_id>/.default&
|
||||||
|
client_secret=<application_client_secret>
|
||||||
|
```
|
||||||
|
|
||||||
|
The JWT returned from the request above can be used with authentik to exchange it for an authentik JWT.
|
||||||
|
@ -80,7 +80,7 @@ module.exports = async function (): Promise<Config> {
|
|||||||
prism: {
|
prism: {
|
||||||
theme: prismThemes.oneLight,
|
theme: prismThemes.oneLight,
|
||||||
darkTheme: prismThemes.oneDark,
|
darkTheme: prismThemes.oneDark,
|
||||||
additionalLanguages: ["python", "diff", "json"],
|
additionalLanguages: ["python", "diff", "json", "http"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
presets: [
|
presets: [
|
||||||
|
Reference in New Issue
Block a user