Skip to content

Commit

Permalink
providers/oauth2: allow m2m for JWKS without alg in keys (goauthentik…
Browse files Browse the repository at this point in the history
…#12196)

* providers/oauth2: allow m2m for JWKS without alg in keys

Signed-off-by: Jens Langhammer <[email protected]>

* Update index.md

Co-authored-by: Tana M Berry <[email protected]>
Signed-off-by: Jens L. <[email protected]>

* Apply suggestions from code review

Co-authored-by: Tana M Berry <[email protected]>
Signed-off-by: Jens L. <[email protected]>

---------

Signed-off-by: Jens Langhammer <[email protected]>
Signed-off-by: Jens L. <[email protected]>
Co-authored-by: Tana M Berry <[email protected]>
  • Loading branch information
BeryJu and tanberry authored Nov 27, 2024
1 parent c05124c commit f9e8138
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 6 deletions.
5 changes: 4 additions & 1 deletion authentik/providers/oauth2/views/token.py
Original file line number Diff line number Diff line change
Expand Up @@ -393,19 +393,22 @@ def __post_init_client_credentials_jwt(self, request: HttpRequest):
LOGGER.warning("failed to parse JWT for kid lookup", exc=exc)
raise TokenError("invalid_grant") from None
expected_kid = decode_unvalidated["header"]["kid"]
fallback_alg = decode_unvalidated["header"]["alg"]
for source in self.provider.jwks_sources.filter(
oidc_jwks__keys__contains=[{"kid": expected_kid}]
):
LOGGER.debug("verifying JWT with source", source=source.slug)
keys = source.oidc_jwks.get("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"))
try:
parsed_key = PyJWK.from_dict(key)
token = decode(
assertion,
parsed_key.key,
algorithms=[key.get("alg")],
algorithms=[key.get("alg")] if "alg" in key else [fallback_alg],
options={
"verify_aud": False,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Hence identification is based on service-accounts, and authentication is based o

An example request can look like this:

```
```http
POST /application/o/token/ HTTP/1.1
Host: authentik.company
Content-Type: application/x-www-form-urlencoded
Expand Down Expand Up @@ -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:

```
```http
POST /application/o/token/ HTTP/1.1
Host: authentik.company
Content-Type: application/x-www-form-urlencoded
Expand Down
4 changes: 2 additions & 2 deletions website/docs/add-secure-apps/providers/oauth2/device_code.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

```
```http
POST /application/o/device/ HTTP/1.1
Host: authentik.company
Content-Type: application/x-www-form-urlencoded
Expand All @@ -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:

```
```http
POST /application/o/token/ HTTP/1.1
Host: authentik.company
Content-Type: application/x-www-form-urlencoded
Expand Down
19 changes: 19 additions & 0 deletions website/docs/users-sources/sources/social-logins/azure-ad/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,22 @@ return True
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.

### 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.
2 changes: 1 addition & 1 deletion website/docusaurus.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ module.exports = async function (): Promise<Config> {
prism: {
theme: prismThemes.oneLight,
darkTheme: prismThemes.oneDark,
additionalLanguages: ["python", "diff", "json"],
additionalLanguages: ["python", "diff", "json", "http"],
},
},
presets: [
Expand Down

0 comments on commit f9e8138

Please sign in to comment.