diff --git a/docs/assets/device_auth_flow.png b/docs/assets/device_auth_flow.png deleted file mode 100644 index 33381b53b524..000000000000 Binary files a/docs/assets/device_auth_flow.png and /dev/null differ diff --git a/docs/janssen-server/auth-server/authz-details/README.md b/docs/janssen-server/auth-server/authz-details/README.md index 61a90daa7da6..566ca2f47597 100644 --- a/docs/janssen-server/auth-server/authz-details/README.md +++ b/docs/janssen-server/auth-server/authz-details/README.md @@ -60,10 +60,17 @@ Sample Authorization Request ``` POST /jans-auth/restv1/authorize HTTP/1.1 Host: yuriyz-fond-skink.gluu.info +Content-Type: application/x-www-form-urlencoded -response_type=code&client_id=7a29bf35-96ec-4bbd-a05c-15e1ff9f07cc&scope=openid+profile+address+email+phone+user_name&redirect_uri=https%3A%2F%2Fyuriyz-relaxed-jawfish.gluu.info%2Fjans-auth-rp%2Fhome.htm&state=6cdc7701-178c-4653-adac-5c1e9c6c4aba&nonce=b9a1ecc4-548e-475c-8b29-f019417e1aef&prompt=&ui_locales=&claims_locales=&acr_values=&request_session_id=false&authorization_details=%5B%0A++%7B%0A++++%22type%22%3A+%22demo_authz_detail%22%2C%0A++++%22actions%22%3A+%5B%0A++++++%22list_accounts%22%2C%0A++++++%22read_balances%22%0A++++%5D%2C%0A++++%22locations%22%3A+%5B%0A++++++%22https%3A%2F%2Fexample.com%2Faccounts%22%0A++++%5D%2C%0A++++%22ui_representation%22%3A+%22Read+balances+and+list+accounts+at+https%3A%2F%2Fexample.com%2Faccounts%22%0A++%7D%0A%5D +response_type=code&client_id=7a29bf35-96ec-4bbd-a05c-15e1ff9f07cc&scope=openid+profile+address+email+phone+user_name&redirect_uri=https%3A%2F%2Fyuriyz-relaxed-jawfish.gluu.info%2Fjans-auth-rp%2Fhome.htm&state=6cdc7701-178c-4653-adac-5c1e9c6c4aba&nonce=b9a1ecc4-548e-475c-8b29-f019417e1aef&prompt=&ui_locales=&claims_locales=&acr_values=&request_session_id=false&authorization_details=%5B%0A++%7B%0A++++%22type%22%3A+%22demo_authz_detail%22%2C%0A++++%22actions%22%3A+%5B%0A++++++%22list_accounts%22%2C%0A++++++%22read_balances%22%0A++++%5D%2C%0A++++%22locations%22%3A+%5B%0A++++++%22https%3A%2F%2Fexample.com%2Faccounts%22%0A++++%5D%2C%0A++++%22ui_representation%22%3A+%22Read+balances+and+list+accounts+at+https%3A%2F%2Fexample.com%2Faccounts%22%0A++%7D%0A%5D&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM&code_challenge_method=S256 ``` +For the Authorization Code flow, clients should use PKCE with the `S256` +code challenge method. The client generates a `code_verifier`, derives +the `code_challenge` using SHA-256 and Base64URL encoding, and includes +the challenge in the authorization request. The original `code_verifier` +is sent during the subsequent token request. + Request is rejected if request's `authorization_details` has types which does not have corresponding `AuthzDetailType` custom script. Check more details about [`AuthzDetailType` custom scripts](../../../script-catalog/authz_detail/AuthzDetail.java) @@ -98,7 +105,7 @@ Content-Type: application/json Accept: application/json { - "grant_types" : [ "authorization_code", "implicit" ], + "grant_types" : [ "authorization_code" ], "subject_type" : "public", "application_type" : "web", "authorization_details_types" : [ "demo_authz_detail" ], @@ -148,8 +155,7 @@ X-Xss-Protection: 1; mode=block "id_token_signed_response_alg": "RS256", "access_token_as_jwt": false, "grant_types": [ - "authorization_code", - "implicit" + "authorization_code" ], "subject_type": "public", "authorization_details_types": ["demo_authz_detail"], diff --git a/docs/janssen-server/auth-server/client-management/client-configuration.md b/docs/janssen-server/auth-server/client-management/client-configuration.md index 050e778a7c66..553dbdb6d576 100644 --- a/docs/janssen-server/auth-server/client-management/client-configuration.md +++ b/docs/janssen-server/auth-server/client-management/client-configuration.md @@ -27,6 +27,13 @@ The client can register a list of URIs as a value for redirect URI parameter. Re matches with the regex provided by the client. Great care should be exercised when using regex to ensure that it accurately matches with the intended patterns only. This feature can be turned on or off via [feature flag](../../reference/json/feature-flags/janssenauthserver-feature-flags.md) + + For new integrations, register exact redirect URIs whenever possible. + Avoid broad regular expressions or wildcard-style matching because + they can allow authorization responses to be redirected to unintended + destinations. Use redirect URI regular expressions only when required + for compatibility, and restrict them to explicitly trusted destinations. + - When using client type as `web`, the redirect URI generally takes the form of `://:/`. It must use `https` schema. The exception to **schema rule** is made when `localhost` or loopback ip `127.0.0.1` is used as the hostname. @@ -114,17 +121,30 @@ tokens. The table below shows grant types and flows that should be used for vari | Client Type | Recommended Grant Type | Flow | |-------------------------------------------------------------------------------------------------|------------------------------------------------|------------------------------| | Backend App (Example: batch processes) that need to access its own resources | `client_credentials` | Client Credentials | -| Server backend of a web-application needs access token | `authorization_code` | Authorization Code | -| Web-application that needs user information via id_token on browser and access token on backend | `authorization_code` | Hybrid Flow | +| Server backend of a web-application needs access token | `authorization_code` | Authorization Code with PKCE | +| Web application requiring an ID token and an access token | `authorization_code` | OpenID Connect Authorization Code with PKCE | | Browser based single page applications or Mobile applications | `authorization_code` | Authorization Code with PKCE | -| Browser based single page applications or Mobile applications that only intend to get id_token | - | Implicit Flow with Form Post | +| Browser-based or mobile application requiring only an ID token | `authorization_code` | OpenID Connect Authorization Code with PKCE | | Input constrained devices (Example: TV) | `urn:ietf:params:oauth:grant-type:device_code` | Device Flow | -| Highly trusted applications where redirect based flows are not feasible to implement | `password` | Resource Owner Password Flow | +| Existing legacy integrations only | `password` (legacy; not recommended) | Resource Owner Password Flow | + +For new applications, use the Authorization Code Flow with PKCE +(`code_challenge_method=S256`) when user authorization is required. +This recommendation applies to both public and confidential clients. + +Janssen Server may continue to support the Implicit Flow, Hybrid Flow, +and Resource Owner Password Credentials Grant for compatibility with +existing applications. However, these flows are not recommended for +new integrations. Existing clients should migrate to the Authorization +Code Flow with PKCE where applicable. !!! Note - Certain grant types should not be used together. For example, implicit flow with hybrid flow. Or using authorization - code flow with hybrid flow. This allows a downgrade attack from more secure flow to less secure flow. + Configure only the grant types and response types required by the + client. Avoid enabling legacy implicit or hybrid response types + alongside Authorization Code Flow unless needed for an existing + integration. Restricting unnecessary response types reduces the + risk of authorization flow downgrade attacks. ## Pre-authorization @@ -146,15 +166,28 @@ Janssen Server's well-known [configuration endpoint](../endpoints/configuration. https://janssen.server.host/jans-auth/.well-known/openid-configuration ``` -Claim `response_types_supported` lists all the supported grant types in the response. +Claim `response_types_supported` lists all the supported response types in the response. When registering client using dynamic client registration, if the `response_type` parameter is not specified, it'll default to `code`. ### Response Type Recommendations -- Avoid using response type `token`. This response type is -[deprecated](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-07#section-10.1) by OAuth 2.1. +- For new integrations, use `response_type=code` with PKCE + (`code_challenge_method=S256`). +- Avoid `response_type=token` and any combination containing it, such as + `id_token token` or `code token`. OAuth 2.1 removes the Implicit Grant. +- Avoid `response_type=id_token` and hybrid types such as `code id_token` + for new integrations. These are OpenID Connect response types and are not + removed by OAuth 2.1, but they return tokens through the browser. Use + `response_type=code` with PKCE to get the ID Token from the token endpoint. +- By default, Janssen Server rejects authorization requests whose + `response_type` contains `token` or `id_token`, because they require the + `implicit` grant type, which is not in the default `grantTypesSupported`. + To support existing applications, add `implicit` to `grantTypesSupported` + and to the client's grant types. Alternatively, set + `allowIdTokenWithoutImplicitGrantType` to `true` to allow `id_token` + without the `implicit` grant. - Grant types allowed for a client determines which response types are permitted in authorization requests. Make sure appropriate grant types are configured in Janssen Server client configuration. Janssen Server will reject authorization requests containing response types not permitted for respective client. diff --git a/docs/janssen-server/auth-server/endpoints/authorization.md b/docs/janssen-server/auth-server/endpoints/authorization.md index f7302cc8f6f4..23cf6c22460c 100644 --- a/docs/janssen-server/auth-server/endpoints/authorization.md +++ b/docs/janssen-server/auth-server/endpoints/authorization.md @@ -7,11 +7,22 @@ tags: --- # Authorization Endpoint +Janssen Server exposes an authorization endpoint defined in +[OAuth 2.0 (RFC 6749)](https://www.rfc-editor.org/rfc/rfc6749#section-3.1), +with security behavior aligned with the +[OAuth 2.1 draft](https://datatracker.ietf.org/doc/draft-ietf-oauth-v2-1/). -Janssen Server exposes authorization endpoint compliant with [OAuth2 framework](https://www.rfc-editor.org/rfc/rfc6749#section-3.1). -A client uses authorization endpoint to obtain an authorization grant. Based on response type requested by the client, -the authorization endpoint issues an authorization code or an access token. Authorization endpoint is a protected endpoint -which will require end-user authentication before issuing authorization code or access token. +A client uses this endpoint to initiate an authorization request and +obtain an authorization grant. + +For new integrations, use the Authorization Code Flow with PKCE +(`code_challenge_method=S256`). The authorization endpoint returns an +authorization code, which the client exchanges for tokens at the token +endpoint after successful end-user authentication and authorization. + +Janssen Server may also support legacy implicit and hybrid response +types, depending on server and client configuration. These response +types are not recommended for new integrations. URL to access authorization endpoint on Janssen Server is listed in the response of Janssen Server's well-known [configuration endpoint](./configuration.md) given below. @@ -57,19 +68,28 @@ navigate via `Auth Server`->`Properties`. ## Required Client Configuration -Clients must be registered with Janssen Server as using [code](https://www.rfc-editor.org/rfc/rfc6749#section-4.1) -and/or [implicit](https://www.rfc-editor.org/rfc/rfc6749#section-4.2) grant types in order to use authorization endpoint. +Clients must be registered for an authorization flow supported by the running server. +Authorization Code is the recommended flow. The Implicit Grant is a legacy option and is +not included in the default supported grant types. Using [Janssen Text-based UI(TUI)](../../config-guide/config-tools/jans-tui/README.md), client can be registered for appropriate grant type by navigating to `Auth-Server`->`Clients`->`Add Client` ## Using PKCE -Janssen Server [supports PKCE](../oauth-features/pkce.md), which recommended and more secure method for using `code` -grant. +Janssen Server [supports PKCE](../oauth-features/pkce.md) for the +Authorization Code Flow. PKCE is required by default, and new integrations +should use the `S256` code challenge method. + +PKCE enforcement is controlled by the +[requirePkce](../../reference/json/properties/janssenauthserver-properties.md#requirepkce) +property, which defaults to `true`. If the global property is set to +`false`, PKCE is still required for clients that have `requirePkce` +enabled individually. -PKCE can be enabled/disable by setting [requirePkce](../../reference/json/properties/janssenauthserver-properties.md#requirepkce) -property. Janssen server supports `plain` as well as `s256` code challenge methods. +When PKCE is required, the client must send a `code_challenge` with +`code_challenge_method=S256` in the authorization request and provide +the corresponding `code_verifier` at the token endpoint. ## Using Request Objects diff --git a/docs/janssen-server/auth-server/endpoints/clientinfo.md b/docs/janssen-server/auth-server/endpoints/clientinfo.md index bb001dda8700..0666a8e7809b 100644 --- a/docs/janssen-server/auth-server/endpoints/clientinfo.md +++ b/docs/janssen-server/auth-server/endpoints/clientinfo.md @@ -30,6 +30,9 @@ Since clientinfo endpoint is an OAuth2 protected resource, a valid access token access the endpoint. More information about request and response of the clientinfo endpoint can be found in the OpenAPI specification of [jans-auth-server module](https://gluu.org/swagger-ui/?url=https://raw.githubusercontent.com/JanssenProject/jans/vreplace-janssen-version/jans-auth-server/docs/swagger.yaml#/Client_Info). +Send this access token in the HTTP `Authorization: Bearer` header and do not send as a URL query +parameter. + ## Disabling The Endpoint Using Feature Flag `/clientinfo` endpoint can be enabled or disable using [clientinfo feature flag](../../reference/json/feature-flags/janssenauthserver-feature-flags.md#clientinfo). diff --git a/docs/janssen-server/auth-server/endpoints/introspection.md b/docs/janssen-server/auth-server/endpoints/introspection.md index 25be7b6b0acf..5b20f6dd4608 100644 --- a/docs/janssen-server/auth-server/endpoints/introspection.md +++ b/docs/janssen-server/auth-server/endpoints/introspection.md @@ -29,12 +29,25 @@ the OpenAPI specification of [jans-auth-server module](https://gluu.org/swagger- - `token_type_hint` - OPTIONAL. A hint about the type of the token submitted for introspection. Not used in current implementation of the AS. - `response_as_jwt` - OPTIONAL. Boolean value with default value false. If true, returns introspection response as JWT (signed based on client configuration used for authentication to Introspection Endpoint). -## Sample GET Request +The `token` parameter is the token being inspected, and it is distinct from the credential +used to authenticate the caller to the introspection endpoint. Authenticate the request +using the configured client authentication method or an `Authorization: Bearer` header +where supported. + +## Sample POST Request (recommended) + +Send the token being inspected in the form-encoded request body. This keeps +it out of URLs, which servers, proxies and browsers can log. ### Request ```shell -curl -X 'GET' 'https://janssen.server.host/jans-auth/restv1/introspection?token=368fea2b-be14-4d30-bd57-bcc4cde2033c&response_as_jwt=false' -H 'accept: application/json' -H "Authorization: Bearer 111d51a4-2828-4b47-abce-77034cddcfb5" +curl -X POST 'https://janssen.server.host/jans-auth/restv1/introspection' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/x-www-form-urlencoded' \ + -H 'Authorization: Bearer ' \ + --data-urlencode 'token=' \ + --data-urlencode 'response_as_jwt=false' ``` ### Response @@ -45,29 +58,28 @@ curl -X 'GET' 'https://janssen.server.host/jans-auth/restv1/introspection?toke "iss": "https://janssen.server.host", "active": true, "token_type": "Bearer", - "client_id": "1800.df1bb233-10b8-40ed-bbb9-07da50892a35", - "aud": "1800.df1bb233-10b8-40ed-bbb9-07da50892a35", + "client_id": "3000.5829c1f8-7554-41ab-a7d6-3513a5e9c4ad", + "aud": "3000.5829c1f8-7554-41ab-a7d6-3513a5e9c4ad", "nbf": null, - "scope": "https://jans.io/oauth/config/scripts.write", + "scope": "", "acr_values": null, "cnf": null, - "exp": 1668705523, - "iat": 1668705223, + "exp": 1668941216, + "iat": 1668781885, "jti": null, "username": null } ``` -## Sample POST Request + +## Sample GET Request + +GET is supported for compatibility. It places the inspected token in the URL +query, where it can appear in server, proxy and browser logs. Prefer POST. ### Request ```shell -curl -X 'POST' \ - 'https://janssen.server.host/jans-auth/restv1/introspection' \ - -H 'accept: application/json' \ - -H 'Content-Type: application/x-www-form-urlencoded' \ - -d 'token=eyJra....3ZkB-Ajwg' - -H "Authorization: Bearer eyJra...BpKo7g" +curl -X 'GET' 'https://janssen.server.host/jans-auth/restv1/introspection?token=368fea2b-be14-4d30-bd57-bcc4cde2033c&response_as_jwt=false' -H 'accept: application/json' -H "Authorization: Bearer 111d51a4-2828-4b47-abce-77034cddcfb5" ``` ### Response @@ -78,14 +90,14 @@ curl -X 'POST' \ "iss": "https://janssen.server.host", "active": true, "token_type": "Bearer", - "client_id": "3000.5829c1f8-7554-41ab-a7d6-3513a5e9c4ad", - "aud": "3000.5829c1f8-7554-41ab-a7d6-3513a5e9c4ad", + "client_id": "1800.df1bb233-10b8-40ed-bbb9-07da50892a35", + "aud": "1800.df1bb233-10b8-40ed-bbb9-07da50892a35", "nbf": null, - "scope": "", + "scope": "https://jans.io/oauth/config/scripts.write", "acr_values": null, "cnf": null, - "exp": 1668941216, - "iat": 1668781885, + "exp": 1668705523, + "iat": 1668705223, "jti": null, "username": null } diff --git a/docs/janssen-server/auth-server/endpoints/token.md b/docs/janssen-server/auth-server/endpoints/token.md index f8146ee7e2fa..0b479f01007e 100644 --- a/docs/janssen-server/auth-server/endpoints/token.md +++ b/docs/janssen-server/auth-server/endpoints/token.md @@ -13,9 +13,14 @@ Token endpoint is defined in the [OAuth 2.0 framework](https://datatracker.ietf. [OpenID Connect](https://openid.net/specs/openid-connect-core-1_0.html) specification and other specifications relevant to them. -Tokens granted by this endpoint depends on grant type and scopes that are specified in the token request. The token -endpoint is used with every authorization grant type except for the implicit grant type (since an access token is issued -directly). +Tokens issued by this endpoint depend on the grant type, requested scopes, +and applicable client and server configuration. The endpoint processes +grant types supported and enabled by the running server. + +The Implicit Grant is a legacy flow in which access tokens are issued +directly from the authorization endpoint rather than the token endpoint. +It is not recommended for new integrations and is not included in the +default supported grant types. Based on request, this endpoint can grant following types of tokens: @@ -129,15 +134,20 @@ navigate via `Auth Server`->`Clients`->`Add Client`->`Basic`-> `Authn Method Tok Token endpoint supports below mentioned grant types. - [Authorization Code](../oauth-features/auth-code-grant.md) -- [Implicit](../oauth-features/implicit-grant.md) - [Refresh Token](../oauth-features/README.md) - [Client Credentials](../oauth-features/client-credential-grant.md) -- [Password](../oauth-features/password-grant.md) - [Token Exchange](../oauth-features/token-exchange.md) - [Transaction Tokens](../tokens/oauth-tx-tokens.md) - [Device Grant](../oauth-features/device-grant.md) - [JWT Grant](../oauth-features/jwt-grant.md) +- [UMA](../uma-features/rpt-endpoint.md) - [CIBA](./backchannel-authentication.md) +- [Password](../oauth-features/password-grant.md) (legacy; not recommended). + Not in the default `grantTypesSupported`. Add `password` to + `grantTypesSupported` and to the client's grant types to use it. + +The [Implicit](../oauth-features/implicit-grant.md) grant (legacy) does not +use the token endpoint. Its tokens come from the authorization endpoint. Client can configure all the possible grant types it can request from token endpoint during client configuration. To select the available grant types using diff --git a/docs/janssen-server/auth-server/endpoints/userinfo.md b/docs/janssen-server/auth-server/endpoints/userinfo.md index 4d0dc564a6fa..c277d3d9803c 100644 --- a/docs/janssen-server/auth-server/endpoints/userinfo.md +++ b/docs/janssen-server/auth-server/endpoints/userinfo.md @@ -11,6 +11,9 @@ tags: Userinfo endpoint is an OAuth2 protected endpoint that is used to retrieve claims about an authenticated end-user. Userinfo endpoint is defined in the [OpenID Connect specification](https://openid.net/specs/openid-connect-core-1_0.html#UserInfo). +Send the access token that authorizes the UserInfo request in the HTTP +`Authorization: Bearer` header. Do not send this access token in the URL query string. + URL to access userinfo endpoint on Janssen Server is listed in the response of Janssen Server's well-known [configuration endpoint](./configuration.md) given below. diff --git a/docs/janssen-server/auth-server/oauth-features/README.md b/docs/janssen-server/auth-server/oauth-features/README.md index 0be494a4e129..4d3803d781ad 100644 --- a/docs/janssen-server/auth-server/oauth-features/README.md +++ b/docs/janssen-server/auth-server/oauth-features/README.md @@ -6,9 +6,21 @@ tags: - feature --- -# OpenID Connect Provider (OP) -The [Janssen Authentication Server](https://github.com/JanssenProject/jans/tree/main/jans-auth-server) has core OAuth 2.0 support as well as many other related specs: +# OAuth 2.1 and OAuth 2.0 +The [Janssen Authentication Server](https://github.com/JanssenProject/jans/tree/main/jans-auth-server) follows OAuth 2.1 by default, along with related specifications and extensions. Out of the box: + +- The Authorization Code Grant requires Proof Key for Code Exchange (PKCE) with the `S256` challenge method. The `plain` method is not accepted. +- The Implicit Grant and the Resource Owner Password Credentials (ROPC) Grant are not in the default supported grant types. +- The UserInfo endpoint does not accept access tokens in the URL query. +- Public clients receive a new refresh token on every refresh. +- Authorization responses include the `iss` parameter. + +For backward compatibility, Janssen still supports OAuth 2.0 features that OAuth 2.1 removes or discourages. See [Enabling Legacy OAuth 2.0 Features](#enabling-legacy-oauth-20-features). + +The Janssen Authentication Server supports the following OAuth specifications and related extensions: + +- The OAuth 2.1 Authorization Framework [(spec draft)](https://datatracker.ietf.org/doc/draft-ietf-oauth-v2-1/) - The OAuth 2.0 Authorization Framework [(spec)](https://datatracker.ietf.org/doc/html/rfc6749) - The OAuth 2.0 Authorization Framework: Bearer Token Usage [(spec)](https://datatracker.ietf.org/doc/html/rfc6750) - JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens [(spec)](https://datatracker.ietf.org/doc/html/rfc9068) @@ -18,11 +30,11 @@ The [Janssen Authentication Server](https://github.com/JanssenProject/jans/tree/ - OAuth 2.0 Token Revocation [(spec)](https://datatracker.ietf.org/doc/html/rfc7009) - Proof Key for Code Exchange by OAuth Public Clients (PKCE) [(spec)](https://datatracker.ietf.org/doc/html/rfc7636) - OAuth 2.0 for Native Apps [(spec)](https://datatracker.ietf.org/doc/html/rfc8252) -- OAuth 2.0 Token Exchange [(spec)](https://datatracker.ietf.org/doc/html/rfc8252) +- OAuth 2.0 Token Exchange [(spec)](https://datatracker.ietf.org/doc/html/rfc8693) - OAuth 2.0 Authorization Server Metadata [(spec)](https://datatracker.ietf.org/doc/html/rfc8414) - OAuth 2.0 Dynamic Client Registration Protocol [(spec)](https://datatracker.ietf.org/doc/html/rfc7591) - OAuth 2.0 Pushed Authorization Requests [(spec)](https://datatracker.ietf.org/doc/html/rfc9126) -- OAuth 2.0 Demonstrating Proof-of-Possession at the Application Layer (DPoP) [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-dpop) +- OAuth 2.0 Demonstrating Proof-of-Possession (DPoP) [(spec)](https://datatracker.ietf.org/doc/html/rfc9449) - OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens [(spec)](https://datatracker.ietf.org/doc/html/rfc8705) - Assertion Framework for OAuth 2.0 Client Authentication and Authorization Grants [(spec)](https://www.rfc-editor.org/rfc/rfc7521.html) - JWT Secured Authorization Response Mode for OAuth 2.0 (JARM) [(spec)](https://openid.net/specs/oauth-v2-jarm.html) @@ -38,9 +50,13 @@ The [Janssen Authentication Server](https://github.com/JanssenProject/jans/tree/ ## Protocol Overview -OAuth 2.0 is the industry-standard protocol for authorization. OAuth 2.0 focuses on client developer simplicity providing specific authorization flows for different applications (e.g. web applications, desktop applications, mobile phones, and other devices). +OAuth 2.0 is the industry-standard framework for authorization. OAuth 2.1 builds on +OAuth 2.0 with updated security recommendations and safer defaults for authorization +flows across different types of applications. + +For new applications, use the Authorization Code Grant with PKCE. OAuth 2.0 grants removed by OAuth 2.1 do remain available in Janssen when explicitly enabled. -It's handy to know some OAuth 2.0 terminology: +OAuth defines the following four primary roles: - **resource owner** - An entity capable of granting access to a protected resource. When the resource owner is a person, it is referred to as an end-user. @@ -56,6 +72,35 @@ It's handy to know some OAuth 2.0 terminology: - **authorization server** - The server issuing access tokens to the client after successfully authenticating the resource owner and obtaining authorization. +## Enabling Legacy OAuth 2.0 Features + +Janssen supports OAuth 2.0 features that OAuth 2.1 removes or discourages, so that existing +applications keep working. Each feature has its own setting; there is no single switch. +These options are not recommended for new integrations. + +| Legacy feature | Setting | +| --- | --- | +| [Implicit Grant](./implicit-grant.md) (`response_type=token`) | Add `implicit` to [`grantTypesSupported`](../../reference/json/properties/janssenauthserver-properties.md#granttypessupported) and to the client's grant types | +| OpenID Connect `id_token` and hybrid response types, such as `code id_token` | Same as the Implicit Grant, or set [`allowIdTokenWithoutImplicitGrantType`](../../reference/json/properties/janssenauthserver-properties.md#allowidtokenwithoutimplicitgranttype) to `true` to allow `id_token` without the `implicit` grant | +| [Password Grant](./password-grant.md) (Resource Owner Password Credentials) | Add `password` to [`grantTypesSupported`](../../reference/json/properties/janssenauthserver-properties.md#granttypessupported) and to the client's grant types | +| Authorization Code without PKCE | Set [`requirePkce`](../../reference/json/properties/janssenauthserver-properties.md#requirepkce) to `false`. PKCE is still required for clients that have `requirePkce` enabled in their own attributes | +| Authorization responses without the `iss` parameter | Set [`authorizationResponseIssParameterSupported`](../../reference/json/properties/janssenauthserver-properties.md#authorizationresponseissparametersupported) to `false`. See [Issuer Identification](./authorization-server-issuer-identification.md) | + +Server properties are set using +[Janssen Text-based UI(TUI)](../../config-guide/config-tools/jans-tui/README.md) via +`Auth Server`->`Properties`. A client's grant types are set via +`Auth Server`->`Clients`->select the client->`Basic`->`Grant`. + +For clients registered using dynamic client registration, the requested grant types must also be in +[`grantTypesSupportedByDynamicRegistration`](../../reference/json/properties/janssenauthserver-properties.md#granttypessupportedbydynamicregistration). +The default value already includes `implicit` and `password`. + +The following OAuth 2.0 behaviors cannot be re-enabled: + +- The PKCE `plain` code challenge method. Only `S256` is accepted. +- Keeping the same refresh token for public clients. A public client always receives a new + refresh token on refresh, even when `skipRefreshTokenDuringRefreshing` is `true`. + ## Have questions in the meantime? You can ask questions through [GitHub Discussions](https://github.com/JanssenProject/jans/discussions) or the [community chat on Zulip](https://chat.gluu.org/join/wnsm743ho6byd57r4he2yihn/). Any questions you have will help determine what information our documentation should cover. diff --git a/docs/janssen-server/auth-server/oauth-features/auth-code-grant.md b/docs/janssen-server/auth-server/oauth-features/auth-code-grant.md index 1d18b6ad12ea..981d983d9e0a 100644 --- a/docs/janssen-server/auth-server/oauth-features/auth-code-grant.md +++ b/docs/janssen-server/auth-server/oauth-features/auth-code-grant.md @@ -8,34 +8,38 @@ tags: - code --- -# OAuth 2.0 Authorization Code Grant +# Authorization Code Grant + +The [Authorization Code Grant](https://datatracker.ietf.org/doc/html/rfc6749#section-4.1) enables public and confidential clients to obtain access tokens through an authorization code issued by the Janssen Authentication Server. + +The client initiates an authorization request and redirects the user to Janssen for authentication and, when required, consent. After successful authorization, Janssen redirects the user back to the client's registered redirect URI with an authorization code. The client then exchanges this code at the token endpoint to obtain an access token and, when applicable, additional tokens. + +Janssen requires Proof Key for Code Exchange (PKCE) by default for the Authorization Code Grant, using the `S256` code challenge method. PKCE binds the authorization request to the token request and helps protect against authorization code interception. Legacy configurations may allow PKCE enforcement to be disabled, but PKCE should remain enabled for OAuth 2.1-aligned applications. -The [Authorization Code grant type](https://tools.ietf.org/html/rfc6749#section-1.3.1) is used by confidential and public clients to exchange an authorization code for an access token. -After the user returns to the client via the redirect URL, the application will get the authorization code from the URL and use it to request an access token. ### Sequence Diagram ```mermaid sequenceDiagram - title Authorization code flow - autonumber 1 + title Authorization Code Flow with PKCE + autonumber - participant User as Resource owner User + participant User as Resource owner User participant Client participant Jans as Jans AS participant RS as Resource Server - activate User - Client->>Jans: Authorization Request - activate Client + Client->>Client: Generate code_verifier and code_challenge (S256) + Client->>Jans: Authorization Request (code_challenge, code_challenge_method=S256) + activate Client activate Jans User->>Jans: User login and consent Jans-->>Client: Authorization code response deactivate Client deactivate Jans - Client->>Jans: Exchange code for Access Token + Client->>Jans: Exchange code for Access Token (code_verifier) activate Client activate Jans Jans-->>Client: Access Token with optional Refresh Token @@ -58,24 +62,29 @@ sequenceDiagram deactivate Client deactivate RS - Client->>Jans: Refresh Token - activate Client - activate Jans - Jans-->>Client: Access Token with optional Refresh Token - deactivate Client - deactivate Jans - deactivate User + opt Refresh Token available + Client->>Jans: Refresh Token Request + activate Client + activate Jans + Jans-->>Client: Access Token with optional Refresh Token + deactivate Client + deactivate Jans + end ``` ### Testing -1. https://github.com/JanssenProject/jans/blob/main/jans-auth-server/client/src/test/java/io/jans/as/client/ws/rs/AuthorizationCodeFlowHttpTest.java +1. Refer to the [Authorization Code Flow integration test](https://github.com/JanssenProject/jans/blob/main/jans-auth-server/client/src/test/java/io/jans/as/client/ws/rs/AuthorizationCodeFlowHttpTest.java) 2. On a browser access -`https://my.jans.server/jans-auth/restv1/authorize?redirect_uri=https://my-redirect-app:8080&client_id=Put_client_id_here&scope=username+openid&response_type=code` -Based on the default authentication method set (acr), the user will be presented with credentials for login. The OpenID Provider (Gluu Server) verifies the user’s identity and authenticates the user. -In the back channel the following steps take place : -- The OpenID Provider (Gluu Server) sends the user back to the application with an authorization code. -- The application sends the code to the Token Endpoint to receive an Access Token and ID Token in the response. -- The application uses the ID Token to authorize the user. At this point the application/RP can access the UserInfo endpoint for claims. +`https://my.jans.server/jans-auth/restv1/authorize?redirect_uri=https%3A%2F%2Fmy-redirect-app%3A8080&client_id=Put_client_id_here&scope=openid%20profile&response_type=code&code_challenge=GENERATED_CODE_CHALLENGE&code_challenge_method=S256&state=RANDOM_STATE_VALUE` + + Based on the configured authentication method (`acr`), the Janssen Authentication Server prompts the user to authenticate and obtains consent when required. + +3. After successful authentication, the following steps take place: + - Janssen redirects the user back to the application's registered redirect URI with an authorization code. + - The application sends the authorization code and the original PKCE `code_verifier` to the Janssen token endpoint. + - Janssen validates the authorization code and PKCE verifier, then issues an access token and, for an OpenID Connect request containing the `openid` scope, an ID token. A refresh token may also be issued when applicable. + - The application validates the ID token to obtain authentication information about the user and uses the access token to access protected resources or retrieve user claims from the UserInfo endpoint. + \ No newline at end of file diff --git a/docs/janssen-server/auth-server/oauth-features/authorization-server-issuer-identification.md b/docs/janssen-server/auth-server/oauth-features/authorization-server-issuer-identification.md index 5dd9719ad8d5..e1c76625a3a8 100644 --- a/docs/janssen-server/auth-server/oauth-features/authorization-server-issuer-identification.md +++ b/docs/janssen-server/auth-server/oauth-features/authorization-server-issuer-identification.md @@ -11,8 +11,8 @@ tags: # Authorization Server Issuer Identification (RFC 9207) Janssen Server supports OAuth 2.0 Authorization Server Issuer Identification as defined in -[RFC 9207](https://datatracker.ietf.org/doc/html/rfc9207). When enabled, the authorization -server includes its own issuer identifier (`iss`) in every authorization response — both +[RFC 9207](https://datatracker.ietf.org/doc/html/rfc9207). By default, the authorization +server includes its own issuer identifier (`iss`) in authorization responses — both successful responses and redirect-based error responses — so that clients can detect and reject mix-up attacks. @@ -30,9 +30,10 @@ expected, and rejects the response if they do not match. ## How It Works -When `authorizationResponseIssParameterSupported` is set to `true` in Janssen Server -configuration, the `iss` parameter is appended to every authorization redirect sent back to -the client's `redirect_uri`. +When `authorizationResponseIssParameterSupported` is `true` in Janssen Server +configuration, the `iss` parameter is appended to every non-JARM authorization redirect sent +back to the client's `redirect_uri`, except for JARM responses, where the issuer is included +in the JWT authorization response. This is the default. ### Successful Authorization Response @@ -68,11 +69,11 @@ sequenceDiagram participant AS as Authorization Server Client->>UA: Redirect to /authorize - UA->>AS: GET /authorize?response_type=code&client_id=...&state=xyz + UA->>AS: GET /authorize?response_type=code&client_id=...&state=xyz&code_challenge=...&code_challenge_method=S256 AS->>UA: 302 redirect_uri?code=...&state=xyz&iss=https://server.example.com UA->>Client: code + state + iss Client->>Client: Verify iss == expected issuer - Client->>AS: POST /token (code exchange) + Client->>AS: POST /token (code + code_verifier) AS->>Client: access_token ``` @@ -89,8 +90,10 @@ the OpenID Connect discovery document at `/.well-known/openid-configuration`: } ``` -Clients that read this metadata entry know they MUST validate the `iss` parameter in every -authorization response they receive from this server. +For non-JARM authorization responses, the client must validate the `iss` +authorization response parameter against the expected issuer. For JARM +responses, the client must validate the `iss` claim in the JWT authorization +response instead. ## Relationship to JARM @@ -105,17 +108,18 @@ The issuer is already secured inside the JWT. ## Configuring Janssen Server -Issuer identification is **opt-in** and disabled by default so that existing deployments -are unaffected. To enable it, set the following property: +Issuer identification is enabled by default. To disable it for compatibility with clients +that cannot process the parameter, set the following property: | Property | Type | Default | Description | |---|---|---|---| -| `authorizationResponseIssParameterSupported` | Boolean | `false` | When `true`, the `iss` parameter is added to all authorization redirect responses per RFC 9207. | +| `authorizationResponseIssParameterSupported` | Boolean | `true` | When `true`, the `iss` parameter is added to authorization redirect responses per RFC 9207. | ### Using the TUI Navigate to **Auth Server → Configuration → Properties** and set -`authorizationResponseIssParameterSupported` to `true`. +`authorizationResponseIssParameterSupported` to `false` only when compatibility requires +disabling issuer identification. ### Using the Config API @@ -123,7 +127,7 @@ Navigate to **Auth Server → Configuration → Properties** and set curl -X PATCH https:///jans-config-api/api/v1/jans-auth-server/config \ -H "Authorization: Bearer " \ -H "Content-Type: application/json-patch+json" \ - -d '[{"op":"replace","path":"/authorizationResponseIssParameterSupported","value":true}]' + -d '[{"op":"replace","path":"/authorizationResponseIssParameterSupported","value":false}]' ``` See the [configuration reference](../../../janssen-server/reference/json/properties/janssenauthserver-properties.md#authorizationresponseissparametersupported) @@ -134,7 +138,9 @@ for the full property description. When a client receives an authorization response from a server that has advertised `authorization_response_iss_parameter_supported: true`, it MUST: -1. Extract the `iss` parameter from the redirect response. +1. For non-JARM authorization responses, extract the `iss` parameter from the + redirect response. For JARM responses, extract the `iss` claim from the + validated JWT authorization response. 2. Compare its value to the expected issuer identifier using simple string comparison (as defined in [RFC 3986 §6.2.1](https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.1)). 3. Reject the response if `iss` is absent or does not match the expected value. diff --git a/docs/janssen-server/auth-server/oauth-features/cimd.md b/docs/janssen-server/auth-server/oauth-features/cimd.md index f5fcd389f418..c95b407756fb 100644 --- a/docs/janssen-server/auth-server/oauth-features/cimd.md +++ b/docs/janssen-server/auth-server/oauth-features/cimd.md @@ -153,6 +153,8 @@ GET /authorize &redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback &scope=openid &state=abc123 + &code_challenge= + &code_challenge_method=S256 ``` No prior registration is required. The server resolves the metadata on the first request. diff --git a/docs/janssen-server/auth-server/oauth-features/client-credential-grant.md b/docs/janssen-server/auth-server/oauth-features/client-credential-grant.md index 2d455a89e32d..b8d4b283070a 100644 --- a/docs/janssen-server/auth-server/oauth-features/client-credential-grant.md +++ b/docs/janssen-server/auth-server/oauth-features/client-credential-grant.md @@ -8,32 +8,52 @@ tags: - client-credentials --- -# OAuth 2.0 client credentials Grant +# Client credentials Grant + +The [Client Credentials Grant](https://datatracker.ietf.org/doc/html/rfc6749#section-4.4) allows a confidential client to obtain an access token from the Janssen Authentication Server using its own credentials, without involving an end-user. + +This grant is commonly used for machine-to-machine (M2M) communication, where an application or service needs to access protected resources on its own behalf. The client authenticates directly with the Janssen token endpoint and receives an access token based on its authorized scopes. ### Sequence Diagram ```mermaid sequenceDiagram - title Client credentials flow - autonumber 1 + title Client Credentials Flow + autonumber participant Client as Resource owner Client - participant JansAS as Jans AS + participant Jans as Jans AS - activate Client - Client->>JansAS:Client Authentication - activate JansAS - JansAS-->>Client:Access Token - deactivate JansAS + Client->>Jans: Token Request (grant_type=client_credentials, client authentication) + activate Jans + Jans-->>Client: Access Token + deactivate Jans ``` ### Testing -1. https://github.com/JanssenProject/jans/blob/main/jans-auth-server/client/src/test/java/io/jans/as/client/ws/rs/ClientCredentialsGrantHttpTest.java +1. Refer to the [Client Credentials Grant integration test](https://github.com/JanssenProject/jans/blob/main/jans-auth-server/client/src/test/java/io/jans/as/client/ws/rs/ClientCredentialsGrantHttpTest.java) + +2. Send a token request to the Janssen Authentication Server using the Client Credentials Grant. + For a client registered with `client_secret_basic`, send the credentials in the HTTP Basic + `Authorization` header: -2. CURL Command: +```bash + curl -X POST "https://my.jans.server/jans-auth/restv1/token" \ + -u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \ + -d "grant_type=client_credentials" \ + --data-urlencode "scope=YOUR_SCOPE" ``` -curl -k -u "put_client_id:put_client_secret" https://jans-ui.jans.io/jans-auth/restv1/token \ - -d "grant_type=client_credentials&scope=put_scope_name_here" + + For a client registered with `client_secret_post`, send the credentials in the request body + instead. The client must have `client_secret_post` as its `token_endpoint_auth_method` or in + its `additional_token_endpoint_auth_methods`: + +```bash + curl -X POST "https://my.jans.server/jans-auth/restv1/token" \ + -d "grant_type=client_credentials" \ + --data-urlencode "client_id=YOUR_CLIENT_ID" \ + --data-urlencode "client_secret=YOUR_CLIENT_SECRET" \ + --data-urlencode "scope=YOUR_SCOPE" ``` diff --git a/docs/janssen-server/auth-server/oauth-features/device-grant.md b/docs/janssen-server/auth-server/oauth-features/device-grant.md index 6d94bcfea428..e466a67d7b52 100644 --- a/docs/janssen-server/auth-server/oauth-features/device-grant.md +++ b/docs/janssen-server/auth-server/oauth-features/device-grant.md @@ -8,40 +8,48 @@ tags: - grant --- -# OAuth 2.0 Device Authorization Grant +# Device Authorization Grant -This OAuth 2.0 protocol extension enables OAuth clients to request user authorization from applications on devices (e.g. smart TVs, media consoles, printers) that are **input-constrained** or **browser-less** . The authorization flow defined by this [RFC 8628](https://tools.ietf.org/html/rfc8628), sometimes referred to as the "device flow", instructs the user to review the authorization request on a secondary device, such as a smartphone or a personal computer, which has the requisite input and browser capabilities to complete the user interaction. +The [OAuth 2.0 Device Authorization Grant (RFC 8628)](https://datatracker.ietf.org/doc/html/rfc8628) enables applications running on input-constrained or browserless devices, such as smart TVs, media consoles, and printers, to obtain user authorization. + +In this flow, the device requests authorization from the Janssen Authentication Server and displays a verification URL and user code. The user opens the verification URL on another device, such as a smartphone or computer, to authenticate and approve the request. Meanwhile, the requesting device polls the Janssen token endpoint until authorization is completed or the request expires. ### Sequence Diagram -![](https://github.com/JanssenProject/jans/raw/main/docs/assets/device_auth_flow.png) -Paste the following source text of the sequence diagram on [sequencediagram.org](https://sequencediagram.org/) -``` -title Oauth2.0 Device Authorization flow - -participant User -participant Browser on Computer / Smartphone -participant Device App -participant Jans AS -participant Third Party App - -User->Device App:Opens an app on device -Device App->Jans AS:Sends authorization request \n"jans-server.com/jans-auth/restv1/device_authorization" -Jans AS->Device App:Response - \nuser_code, device_code, verification_url, interval, expiration -Device App ->User: Instructs the user to access Verification URL \nand enter user_code -note over Device App:Device App will keep polling AS for Access Token \nuntil device authorization is completed -loop till Device App recieves Access Token: -Device App->Jans AS:request Access Token -Jans AS->Device App:Response - \naccess_denied \nOR expired_token \nOR authorization_pending \nOR Access token -end -User->Browser on Computer / Smartphone:Opens a browser \nand access verification URL -Browser on Computer / Smartphone->Jans AS:send user_code to verification URL -Browser on Computer / Smartphone <-Jans AS:Login and authorization prompt -Browser on Computer / Smartphone->Jans AS:Authentication and consent -Jans AS->Jans AS: Mark device as Authorized -note over Jans AS:Subsequent polling by the Device App \nwill return an Access Token as indicated \nby the loop above -Device App->Third Party App:Invoke API with Access Token -Third Party App->Device App: return Response +```mermaid + +sequenceDiagram + title OAuth 2.0 Device Authorization Flow + autonumber + + participant User + participant Browser as User's Browser + participant Device as Device App + participant Jans as Jans AS + participant ThirdParty as Third Party App + + User->>Device: Opens an app on device + Device->>Jans: Device authorization request + Jans-->>Device: user_code, device_code, verification_uri, interval, expires_in + Device-->>User: Display verification URI and user_code + + Note over Device,Jans: Device polls the token endpoint at the required interval + + Device->>Jans: Token request with device_code + Jans-->>Device: authorization_pending + + User->>Browser: Opens verification URI + Browser->>Jans: Submits user_code + Jans-->>Browser: Login and authorization prompt + Browser->>Jans: Authentication and consent + Jans->>Jans: Mark device as authorized + + Device->>Jans: Poll token endpoint with device_code + Jans-->>Device: Access token + + Device->>ThirdParty: Invoke API with access token + ThirdParty-->>Device: API response + ``` ## User Experience @@ -144,7 +152,7 @@ The user will need to put `user_code` value in the browser and after that, he wi Since the user will be using a separate device to navigate to the `verification_url` and grant or deny access, the requesting device is not automatically notified when the user responds to the access request. For that reason, the requesting device needs to poll the Jans Server to determine when the user has responded to the request. -The requesting device should continue sending polling requests until it receives a response indicating that the user has responded to the access request or until the `device_code` expires. The parameter `interval` returned in step 2 specifies the amount of time, in seconds, to wait between requests. +The requesting device continues polling the token endpoint while authorization is pending, until it receives a successful token response, a terminal error, or the `device_code` expires. The `interval` parameter returned by the device authorization endpoint specifies the minimum number of seconds between polling requests. If the server returns a `slow_down` error, the device must increase the polling interval by at least five seconds. The URL of the endpoint to poll is `/jans-auth/restv1/token`. The polling request contains the following parameters: @@ -175,9 +183,9 @@ The Jans authorization server responds to each polling request with one of the f **Access granted** -If the user granted access to the device (by clicking `Allow` on the consent screen), then the response contains an access token and a refresh token. The tokens enable the device to access to the resource server on the user's behalf. +If the user grants access to the device, the Janssen Authentication Server returns an access token. A refresh token and an ID token may also be issued, depending on the requested scopes and server configuration. -In this case, the server responds with all tokens required and allowed to be issued depending on the configuration in the server. +The device can use the access token to access protected resources on the user's behalf. Example: @@ -250,4 +258,5 @@ Server: Jetty(9.4.19.v20190610) This token endpoint can return any error code already defined, for example whether client can't be authenticated or the grant type sent is invalid. Some of them could be: `invalid_client`, `invalid_grant`, `invalid_request` and others. ### Customizing Device Grant page -More about customising [this page](https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/webapp/device_authorization.xhtml) to include your organization's stylesheets, images and content in this [article](https://jans.io/docs/developer/customization/customize-web-pages.md) + +To customize the Device Authorization page with your organization's stylesheets, images, and content, refer to the [Device Authorization page source](https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/webapp/device_authorization.xhtml) and the [Customize Web Pages guide](../../developer/customization/customize-web-pages.md). diff --git a/docs/janssen-server/auth-server/oauth-features/implicit-grant.md b/docs/janssen-server/auth-server/oauth-features/implicit-grant.md index 2c5f3ab4f7b2..0b662e6ca642 100644 --- a/docs/janssen-server/auth-server/oauth-features/implicit-grant.md +++ b/docs/janssen-server/auth-server/oauth-features/implicit-grant.md @@ -10,11 +10,26 @@ tags: # OAuth 2.0 Implicit Grant -The [Implicit Grant](https://tools.ietf.org/html/rfc6749#section-1.3.2) : +!!! warning "Legacy grant" + The Implicit Grant is not included in OAuth 2.1 and is not enabled in + Janssen's default supported grant types. It is not recommended for new + integrations. Legacy deployments may explicitly configure support for + this grant. For new applications, use the Authorization Code Grant with + PKCE (`S256`) instead. Verify the grant types advertised in the + deployment's discovery metadata. -!!! [OAuth 2.0 Security Best Current Practice](https://tools.ietf.org/html/draft-ietf-oauth-security-topics) absolutely discourages the use of Implicit flow. -Instead, use Authorization code flow with PKCE -[OAuth 2.0 for Browser-Based Apps](https://tools.ietf.org/html/draft-ietf-oauth-browser-based-apps). -[Further reading](https://oauth.net/2/grant-types/implicit/) + +The [Implicit Grant](https://datatracker.ietf.org/doc/html/rfc6749#section-4.2) +is a legacy OAuth 2.0 flow in which an access token is returned directly +in the authorization response, without exchanging an authorization code +at the token endpoint. + +The [OAuth 2.0 Security Best Current Practice (RFC 9700)](https://datatracker.ietf.org/doc/html/rfc9700) +recommends against using the Implicit Grant because of security risks +associated with access tokens exposed through the authorization response. + +For additional background, see +[OAuth 2.0 Implicit Grant](https://oauth.net/2/grant-types/implicit/). ### Sequence Diagram @@ -54,4 +69,3 @@ sequenceDiagram ``` - diff --git a/docs/janssen-server/auth-server/oauth-features/jwt-grant.md b/docs/janssen-server/auth-server/oauth-features/jwt-grant.md index 28b1a3c1e114..e19f9f6f0eca 100644 --- a/docs/janssen-server/auth-server/oauth-features/jwt-grant.md +++ b/docs/janssen-server/auth-server/oauth-features/jwt-grant.md @@ -8,19 +8,20 @@ tags: - jwt-grant --- -# OAuth 2.0 JWT Grant +# JWT Bearer Grant -The [JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants spec](https://datatracker.ietf.org/doc/html/rfc7523). +The [JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants (RFC 7523)](https://datatracker.ietf.org/doc/html/rfc7523) defines how JWT assertions can be used to request access tokens from an authorization server. -JWT Grant is identified by `grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer` at Token Endpoint. +The Janssen Authentication Server supports the JWT Bearer Grant using `grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer` at the token endpoint. The client submits a signed JWT assertion, which Janssen validates before issuing an access token. -AS requires client authentication during JWT Grant usage. +Janssen requires client authentication when using the JWT Bearer Grant. -**Assertion validation** -1. Client's `jwks` or `jwks_uri` is used to get keys for `assertion` signature validation +## Assertion Validation + +1. Janssen validates the JWT assertion's signature using the public keys obtained from the client's configured `jwks` or `jwks_uri`. 2. `aud` claim of `assertion` must contain AS `issuer` or otherwise any `aud` claim value must starts from AS `issuer` (for example if Token Endpoint address is set in `aud` claim value) 3. `iss` must not be blank. If AS `trustedSsaIssuers` configuration property is set then AS will validate `iss` value against `trustedSsaIssuers` configuration property. -4. AS validates `exp` on expiration +4. `exp` is required; an assertion without `exp` or with an expired `exp` is rejected 5. AS validates `nbf` if it's present 6. `sub` value must be not empty and not blank @@ -54,6 +55,7 @@ If `jwtGrantAllowUserByUidInAssertion` is `true` and `uid` claim value points to POST /token HTTP/1.1 Host: authz.example.net Content-Type: application/x-www-form-urlencoded +Authorization: Basic grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer &assertion=eyJhbGciOiJFUzI1NiIsImtpZCI6IjE2In0. diff --git a/docs/janssen-server/auth-server/oauth-features/mtls.md b/docs/janssen-server/auth-server/oauth-features/mtls.md index 9263691c805b..f160ef5a0565 100644 --- a/docs/janssen-server/auth-server/oauth-features/mtls.md +++ b/docs/janssen-server/auth-server/oauth-features/mtls.md @@ -10,6 +10,13 @@ tags: # mTLS (Mutual Transport Layer Security) +For OAuth, mutual-TLS client authentication and certificate-bound access tokens +are defined by [RFC 8705](https://datatracker.ietf.org/doc/html/rfc8705), an +OAuth 2.0 specification. This describes the standard mTLS follows; it does not +mean Janssen supports only OAuth 2.0. Janssen also applies OAuth 2.1-aligned +security defaults, including requiring PKCE `S256` for Authorization Code by +default. These defaults do not replace or remove RFC 8705 mTLS support. + ## What Is mTLS? **mTLS** is a process that establishes an encrypted [TLS](https://wikipedia.org/wiki/Transport_Layer_Security) @@ -58,6 +65,20 @@ In practice, mTLS can identify and authorize the following: can be validated by RP. If `access_token` is JWT then `x5t#S256` claim is added to payload of the token. Otherwise, token can be introspected. +The PKI trust-chain validation for `tls_client_auth` is performed by the TLS-terminating +proxy (for example Apache), while Jans checks the forwarded certificate subject against +`tls_client_auth_subject_dn`. For `self_signed_tls_client_auth`, Jans matches the +certificate public key against a key in the client's registered JWKS. Protect the +forwarded-certificate headers: the proxy must remove client-supplied copies and set its +own value only after authenticating the TLS client. + +When Jans creates a certificate-bound access token, the current token-creation path +calculates `x5t#S256` from the `X-ClientCert` request header. Although client +authentication can parse Envoy/Istio and Traefik forwarded-certificate headers too, +the token-binding path reads `X-ClientCert` directly. Ensure the TLS-terminating +proxy supplies the authenticated client certificate in that header for certificate +binding, including by mapping another trusted proxy header to `X-ClientCert` if needed. + ``` { "active": true, @@ -535,76 +556,33 @@ curl --insecure --cert-type P12 --cert example-cli.p12: --locatio "authorization_code" ], "response_types": [ - "code", - "token", - "id_token" + "code" ], "redirect_uris": [ - https:///jans-auth-rp/home.htm + "https:///jans-auth-rp/home.htm" ] }' ``` -Response: +The registration response contains server-generated client details. The following +shows the relevant values for this example; other fields depend on server policy: ```json { - "allow_spontaneous_scopes": false, - "jwks": { - "keys": [ - { - "kty": "RSA", - "e": "AQAB", - "use": "sig", - "kid": "your-kid", - "alg": "RS256", - "n": "5elNNA2wYlUpEK2JxOqIgFe3JmHBs63M7wvKM_cbzXjMpLXn7UqAbIN7drDgLIvsIwSo9DAuWvFV3mLqApFYlL1qQCEveULbh6LorqPUzl2UjHwDDFlM1Hj6JpJ_GbacX5-YnRgXC7k_p4ZIf0GOkQxIo0WVNhulku3z84Ko8Efk5BeV7ImFyXWLoO-ru8h3Yvq2h1LRVYX02LZlG6Mv8dqCJsWHIbnmaB16TSe_HCA3qEA4k9La2fl4R7fPlq1u89LN3kz2M0cm1M8aTTquLHP0tv5EpeqX1pG4VjwurssevguRM9QqrGkPktAw_uzIKfO7s5_j3AD3teYdVQFryQ" - } - ] - }, - "application_type": "web", - "rpt_as_jwt": false, - "registration_client_uri": "https:///jans-auth/restv1/register?client_id=d16994c2-313c-4440-9713-25290fbb89a9", - "tls_client_auth_subject_dn": "", - "run_introspection_script_before_jwt_creation": false, - "registration_access_token": "93a52334-bf79-4414-bc9a-983b6921597c", "client_id": "d16994c2-313c-4440-9713-25290fbb89a9", "token_endpoint_auth_method": "self_signed_tls_client_auth", - "scope": "email openid profile", - "client_secret": "e1c9e9df-e542-4225-adb4-d0590f85d97d", - "client_id_issued_at": 1698114939, - "backchannel_logout_uri": "", - "backchannel_logout_session_required": false, - "client_name": "Test Client mTLS", - "par_lifetime": 600, - "spontaneous_scopes": [], - "id_token_signed_response_alg": "RS256", - "access_token_as_jwt": true, - "grant_types": [ - "implicit", - "refresh_token", - "authorization_code" - ], - "subject_type": "pairwise", - "additional_token_endpoint_auth_methods": [], - "keep_client_authorization_after_expiration": false, - "require_par": false, - "redirect_uris": [ - "https:///jans-auth-rp/home.htm" - ], - "redirect_uris_regex": "", - "additional_audience": [], - "frontchannel_logout_session_required": false, - "client_secret_expires_at": 1698201339, - "access_token_signing_alg": "RS256", - "response_types": [ - "code", - "id_token", - "token" - ] + "grant_types": ["authorization_code"], + "response_types": ["code"] } ``` +The returned grant and response types depend on the server's registration policy. +For this Authorization Code example, verify that the registered client allows +`authorization_code` and has `code` as its response type. Do not rely on legacy +Implicit-flow values appearing in a response. The server may also return a +`client_secret` field for compatibility; it is not used by +`self_signed_tls_client_auth`. + > **NOTE:** To obtain the `jwks` field data, follow the next step. #### P12 to JWKS @@ -634,20 +612,24 @@ Enter pass phrase for PKCS12 import pass phrase: ### 2. Call `authorize` endpoint -From your browser of choice call the following url: +Generate a PKCE verifier and its `S256` challenge for this authorization +request. Use the same verifier in the token request below. Replace the +placeholders in the URL with the generated challenge and your client details: ``` -https:///jans-auth/restv1/authorize?response_type=code&client_id=d16994c2-313c-4440-9713-25290fbb89a9&scope=openid+profil+email&redirect_uri=https:///jans-auth-rp/home.htm&state=f9bb35cb-3485-4ae4-aa8e-63e9a97b6e5d&nonce=4a2f07cb-521b-465c-8b06-0c17711a96a7 +https:///jans-auth/restv1/authorize?response_type=code&client_id=d16994c2-313c-4440-9713-25290fbb89a9&scope=openid+profile+email&redirect_uri=https%3A%2F%2F%2Fjans-auth-rp%2Fhome.htm&state=f9bb35cb-3485-4ae4-aa8e-63e9a97b6e5d&nonce=4a2f07cb-521b-465c-8b06-0c17711a96a7&code_challenge=&code_challenge_method=S256 ``` URL parameters: - `response_type=code` - `client_id=d16994c2-313c-4440-9713-25290fbb89a9` -- `scope=openid+profil+email` +- `scope=openid+profile+email` - `redirect_uri=https:///jans-auth-rp/home.htm` - `state=f9bb35cb-3485-4ae4-aa8e-63e9a97b6e5d` - `nonce=4a2f07cb-521b-465c-8b06-0c17711a96a7` +- `code_challenge=` +- `code_challenge_method=S256` The field we need to obtain is the `code`. @@ -663,19 +645,23 @@ curl --insecure --cert-type P12 --cert example-cli.p12: --locatio --data-urlencode 'grant_type=authorization_code' \ --data-urlencode 'redirect_uri=https:///jans-auth-rp/home.htm' \ --data-urlencode 'client_id=d16994c2-313c-4440-9713-25290fbb89a9' \ ---data-urlencode 'client_secret=' \ ---data-urlencode 'code=' +--data-urlencode 'code=' \ +--data-urlencode 'code_verifier=' ``` +Because this client uses `self_signed_tls_client_auth`, authenticate it with the +client certificate rather than a client secret. Its certificate public key must +match a public key in the registered JWKS. + Response: ```json { - "access_token": "eyJraWQiOiJjb25uZWN0X2NmNjBiZWZmLTU1MzUtNDllNS04MWQ5LTM5ZDM4ZmNlMWNhMF9zaWdfcnMyNTYiLCJ0eXAiOiJqd3QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJNSGdqa2hnTktmZWF4ZUVEY0wycEt5c1EwVUQ4RDk1QUd5NFBGXzI2cmlnIiwiY29kZSI6ImE0NWE5ODI5LTFkMDQtNGQxNS05NjllLWRiMjk3Mzk4ZTdjMyIsImlzcyI6Imh0dHBzOi8vbWlsdG9uLWNoLWhhcmR5LW1pdGUuZ2x1dS5pbmZvIiwidG9rZW5fdHlwZSI6IkJlYXJlciIsImNsaWVudF9pZCI6IjVkODM1NDA3LTFlZjMtNDQxZC04YWU2LTZiYmRkNTcyNzZjYyIsImF1ZCI6IjVkODM1NDA3LTFlZjMtNDQxZC04YWU2LTZiYmRkNTcyNzZjYyIsImFjciI6ImJhc2ljIiwieDV0I1MyNTYiOiJPeHRJQXRBMEMwTkwteTR2UmZLeDd6TExFZXhfWG1DelduUWJ4ejZUem5ZIiwic2NvcGUiOlsib3BlbmlkIiwicHJvZmlsZSIsImVtYWlsIl0sImF1dGhfdGltZSI6MTY5ODE5NDczNiwiZXhwIjoxNjk4Mjc4MDQzLCJpYXQiOjE2OTgxOTY4MzIsInVzZXJuYW1lIjoiRGVmYXVsdCBBZG1pbiBVc2VyIn0.JpK7JYy6Avui3LNbxTKBYJW9fqjEIqijCXPw9fvqEO1kqO7AUozOEof00hPKzJo1Dh7VgGpY89MiAduDUoU3QCemtFsNSd1DCyExl2s3w5OF2mUm6nMzjaS377ZQQ39DAq91OGFFq_ISt4JIhWRf7_xUEvlLRAttTqxE5qp1ZYvgAYu07jbVJX8WqJvxYz3rZ3J-4kq2FLREunRf5KxYaHO-oKzrmhRVPTc_cj1vqwSfu8vRjLmx4P-eN7SgVNa0XmZ8WClLnmchucGBH6rYq3bXZWsOKixwLhno_2vPe1MmbK3XnNNBu_fm_bL2N5kgAwr9b-upoBJc08IyCje1vA", - "refresh_token": "1e58e2c9-4175-4b3f-8170-65544b1a7c48", - "id_token": "eyJraWQiOiJjb25uZWN0X2NmNjBiZWZmLTU1MzUtNDllNS04MWQ5LTM5ZDM4ZmNlMWNhMF9zaWdfcnMyNTYiLCJ0eXAiOiJqd3QiLCJhbGciOiJSUzI1NiJ9.eyJhdF9oYXNoIjoib1NoVDE4YUdRVHdtNXBjT255dkNMUSIsInN1YiI6Ik1IZ2praGdOS2ZlYXhlRURjTDJwS3lzUTBVRDhEOTVBR3k0UEZfMjZyaWciLCJhbXIiOlsiMTAiXSwiaXNzIjoiaHR0cHM6Ly9taWx0b24tY2gtaGFyZHktbWl0ZS5nbHV1LmluZm8iLCJub25jZSI6ImMxNGQ2Y2RlLWQ5NTYtNDM4Zi04Mzk5LTQ3MzdkNWZlOTkyOSIsInNpZCI6IjI2ZTM4YTJmLTEzZTktNGY4Yi05MzdjLTQ3M2ViMjdlNzFkNiIsImphbnNPcGVuSURDb25uZWN0VmVyc2lvbiI6Im9wZW5pZGNvbm5lY3QtMS4wIiwiYXVkIjoiNWQ4MzU0MDctMWVmMy00NDFkLThhZTYtNmJiZGQ1NzI3NmNjIiwicmFuZG9tIjoiMjVhZDViMmUtMGNkMi00Mjg3LTg1M2ItZWY3NWRhZjMzNWMwIiwiYWNyIjoiYmFzaWMiLCJjX2hhc2giOiJwM2ZJVHlGT09fd0tRZW9QT1VkWWF3IiwiYXV0aF90aW1lIjoxNjk4MTk0NzM2LCJleHAiOjE2OTgyMDA0MzIsImdyYW50IjoiYXV0aG9yaXphdGlvbl9jb2RlIiwiaWF0IjoxNjk4MTk2ODMyfQ.GMXkiFGcCy6dXI8gPPuCLd977Gs_rkG1w3FrNx_HlSnmcDUSsEQHvPxpA99Y3L8Z82uLHYCbP5Vga6iCEOmBBHnu9jEsmYgp-TSrB31HV-5g7-o4ZWJG05SdL9KgSP3PyDXRqcE0VFxBJ-uJSyvI-htQ4GUXMIhqVhbJJynPNosXtZvvDVIw1NBThupmqx58cozf5tIdnwaeiuN_Ce2XQrjZBiachI6KWFa-Mstrsdw1E6Ny_4bP-1UmeNgScd6pmIUemGsfclxIAgO0lACqgbGh7wo0PljbhEkGU_i9kP--0KJHkBkUxflULW3aAqdYtG9hEr_JEIddHVxXbi1c_w", + "access_token": "", + "refresh_token": "", + "id_token": "", "token_type": "Bearer", - "expires_in": 81210 + "expires_in": 3600 } ``` @@ -683,6 +669,12 @@ Once we have obtained the `access_token` in `jwt(json web token)` format, we wil ### 4. Call `introspection` endpoint +The client certificate authenticates the TLS connection, but the introspection +endpoint also requires an authorization credential by default. Use the access +token as a Bearer credential as well as the token being introspected: +if [`introspectionAccessTokenMustHaveIntrospectionScope`](../../reference/json/properties/janssenauthserver-properties.md#introspectionaccesstokenmusthaveintrospectionscope) +is enabled, make sure the access token includes the `introspection` scope. + Run below command: ```bash @@ -702,7 +694,7 @@ Response: "active": true, "token_type": "Bearer", "client_id": "d16994c2-313c-4440-9713-25290fbb89a9", - "aud": "5d835407-1ef3-441d-8ae6-6bbdd57276cc", + "aud": "", "acr": "basic", "nbf": null, "scope": "openid profile email", diff --git a/docs/janssen-server/auth-server/oauth-features/password-grant.md b/docs/janssen-server/auth-server/oauth-features/password-grant.md index 1437a64d5329..f14baf55b713 100644 --- a/docs/janssen-server/auth-server/oauth-features/password-grant.md +++ b/docs/janssen-server/auth-server/oauth-features/password-grant.md @@ -10,14 +10,27 @@ tags: # Password Grant -Janssen Server supports the password grant. At the same time, inline with +!!! warning "Legacy grant" + The Resource Owner Password Credentials (ROPC) Grant is not included in + OAuth 2.1 and is not enabled in Janssen's default supported grant types. + It is not recommended for new integrations. Legacy deployments may + explicitly configure support for this grant. For new applications, + use the Authorization Code Grant with PKCE (`S256`) instead. + Verify the grant types advertised in the deployment's discovery metadata. + +Janssen Server can support the password grant when explicitly enabled. At the same time, in line with [OAuth 2.0 security best practices](https://oauth.net/2/oauth-best-practice/), this password grant should never be used in practice. [OAuth 2.1](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-08) has removed this grant type. ## Configuration -A client can use the password grant if it is enabled in the configuration. An administrator can use -[TUI](../../config-guide/config-tools/jans-tui/README.md) to enable password grant for a client. +A client can use the password grant only when it is enabled both for the authorization server and +for that client. Add `password` to the authorization server's +[grantTypesSupported](../../reference/json/properties/janssenauthserver-properties.md#granttypessupported) +property (in TUI, navigate to **Auth Server -> Properties -> grantTypesSupported**), and add +`password` to the client's grant types using +[TUI](../../config-guide/config-tools/jans-tui/README.md). Otherwise, the token endpoint rejects +the request. See the [token endpoint documentation](../endpoints/token.md#token-endpoint) for details. ![](../../../assets/image-tui-client-registration-basic.png) diff --git a/docs/janssen-server/auth-server/oauth-features/pkce.md b/docs/janssen-server/auth-server/oauth-features/pkce.md index d459901d023e..91f7b712c629 100644 --- a/docs/janssen-server/auth-server/oauth-features/pkce.md +++ b/docs/janssen-server/auth-server/oauth-features/pkce.md @@ -9,20 +9,18 @@ tags: # PKCE (Proof Key for Code Exchange) -PKCE(Proof Key for Code Exchange) is an extension to the Authorization on Code -flow to prevent `CSRF` and authorization code injection attacks. Authorization -code flow with PKCE is defined in [this](https://datatracker.ietf.org/doc/html/rfc7636) specification. +Proof Key for Code Exchange (PKCE), defined in +[RFC 7636](https://datatracker.ietf.org/doc/html/rfc7636), is a security +extension to the OAuth Authorization Code Grant. It helps protect against +authorization code interception and injection attacks by binding the +authorization request to the token request. -Public clients (**Single Page Apps (SPA)** or **Mobile Apps**), have a serious -problem obtaining access tokens. In the case of `SPA` you cannot securely store -a secret key, because its source is available in the browser. The same -will happen with **Mobile Apps**, since decompiling the application will reveal -the secret keys. +Public clients, such as Single Page Applications (SPAs) and mobile applications, +cannot securely store client secrets. PKCE protects the authorization code +exchange without requiring a client secret. -This is where `PKCE` comes in to solve the problem. - -The authorization code flow with PKCE is considered as best practice when -using **Single Page Apps (SPA)** or **Mobile Apps**. +Janssen requires PKCE by default for the Authorization Code Grant, including +public and confidential clients, using the `S256` code challenge method. Let's see in the following diagram how it works: @@ -32,18 +30,17 @@ Let's see in the following diagram how it works: ## PKCE Configuration -For this flow to work, we must make the following configuration in -Janssen Server. - -We need to set the `clientAuthenticationFiltersEnabled` property to `false`, it -defaults to `true`. We can use -[TUI](../../config-guide/config-tools/jans-tui/README.md) to change this -configuration as shown below: - -![pkce3.png](../../../assets/pkce3.png) +Janssen requires PKCE for the Authorization Code Grant by default through the +server-level `requirePkce` property. A client can also require PKCE through its +client attributes. Setting the server-level property to `false` does not disable +PKCE for clients that individually require it. -AS requires PKCE if `requirePkce` global AS configuration property is set to `true` or otherwise if -client involved in request has `requirePkce` set to `true` in client attributes (inside `jansAttrs` json). +For requests processed through the authorization endpoint, only the `S256` +code challenge method is accepted. Requests using `plain`, an unsupported +method, or a `code_challenge` without an explicit +`code_challenge_method=S256` are rejected. See the +[authorization-server configuration](../../config-guide/auth-server-config/jans-authorization-server-config.md) +and the [`requirePkce` property reference](../../reference/json/properties/janssenauthserver-properties.md#requirepkce). ## Authorization Code Flow + PKCE @@ -81,16 +78,13 @@ MW54l5Ma7i8n6QsetI_dnJhfMQ6gIfBNJiWFINu6rtD0zvZUXG3STWoolT5HFatjWu2Vj1L-Au4PtRzk To generate the `code_challenge` we need to know what type of method we will be using, so this field is accompanied by the `code_challenge_method` field. -Janssen Server supports two methods of `code_challenge_method`: +Janssen Server requires `code_challenge_method=S256`. The `code_challenge` is +the base64url-encoded SHA-256 digest of the `code_verifier`. -- `plain`: When using this method, the `code_challenge` is the same as the `code_verifier`. -- `s256`: When using this method, `code_challenge` must be encoded using the `code_verifier` with **sha256** and * - *base64Url**. - -The following command generates the `code_challenge` using `s256`. +The following command generates the `code_challenge` using `S256`. !!! Note - To execute command the command below, you need to have `openssl`, `basenc` + To execute the command below, you need to have `openssl`, `basenc` and `tr` installed. ```bash @@ -123,9 +117,7 @@ Content-Type: application/json "authorization_code" ], "response_types": [ - "code", - "token", - "id_token" + "code" ], "redirect_uris": [ "https:///jans-auth-rp/home.htm" @@ -134,7 +126,7 @@ Content-Type: application/json ``` !!! Note - Notee that the `token_endpoint_auth_method` field is `none`. + Note that the `token_endpoint_auth_method` field is `none`. ```text title="Response" HTTP/1.1 201 Created @@ -155,7 +147,7 @@ Connection: close "allow_spontaneous_scopes": false, "application_type": "web", "rpt_as_jwt": false, - "registration_client_uri": "https:///jans-auth/restv1/register?client_id=057c3abf-a1a7-49cc-9e4e-8737e898ac72", + "registration_client_uri": "https:///jans-auth/restv1/register?client_id=f48fbdfa-4c07-49e5-938b-10463980e145", "tls_client_auth_subject_dn": "", "run_introspection_script_before_jwt_creation": false, "registration_access_token": "659ccbf9-ac98-437a-b952-33bfc0366fc2", @@ -172,8 +164,6 @@ Connection: close "id_token_signed_response_alg": "RS256", "access_token_as_jwt": false, "grant_types": [ - "implicit", - "refresh_token", "authorization_code" ], "subject_type": "pairwise", @@ -189,9 +179,7 @@ Connection: close "client_secret_expires_at": 1700347873, "access_token_signing_alg": "RS256", "response_types": [ - "code", - "token", - "id_token" + "code" ] } ``` @@ -209,7 +197,7 @@ redirect_uri=https:///jans-auth-rp/home.htm& state=bf1af4a1-8713-49c6-b229-537bf4cf712d& nonce=f2265e46-6d93-4d36-850b-8fd990cccd04& code_challenge=& -code_challenge_method= +code_challenge_method=S256 ``` !!! Note @@ -237,12 +225,9 @@ code= ```json title="Response" { - "access_token": "38abc903-9a68-48f9-9ccc-bf1b50fe8152", - "refresh_token": "e945e8ab-19c1-4073-b3c1-913bb090459a", - "id_token": "eyJraWQiOiJjb25uZWN0XzZmZmJkZTQ3LTU5MDgtNDljMy04MGVkLTFjODNhNGEyNWJmOF9zaWdfcnMyNTYiLCJ0eXAiOiJqd3QiLCJhbGciOiJSUzI1NiJ9.eyJhdF9oYXNoIjoiTndiVXg2NlFaUzFvMG1SMmdyRGxKZyIsInN1YiI6IkcxM2ZtQ3RDQkJ0VDN5TzBMWUY0eng3X1ROUktZeGhGNUd6cGFYOUFiZlkiLCJhbXIiOlsiMTAiXSwiaXNzIjoiaHR0cHM6Ly9taWx0b24tY2gtaGFyZHktbWl0ZS5nbHV1LmluZm8iLCJub25jZSI6IjRlOWVhZjdjLWZlMjUtNDlkMC05OGU1LTM2ZTNjYzJhMWNiZCIsInNpZCI6IjIwZThmNTAzLWZmN2EtNGU3OS05OTY3LTUxMTU5NTk1N2JhYiIsImphbnNPcGVuSURDb25uZWN0VmVyc2lvbiI6Im9wZW5pZGNvbm5lY3QtMS4wIiwiYXVkIjoiN2M3OGE0MmUtNTc4YS00OWE2LWExNzAtZTg1N2E0NWYzNTBjIiwicmFuZG9tIjoiZGU0NjE5NDEtNzIzOC00YjZjLWI2NTQtNjg2OTU0MmZlZjc3IiwiYWNyIjoiYmFzaWMiLCJjX2hhc2giOiJ1eFlZWDc5a3c2S2llX0NvaTZERi1RIiwiYXV0aF90aW1lIjoxNzAwMzYxMzA1LCJleHAiOjE3MDAzNjY5MjIsImdyYW50IjoiYXV0aG9yaXphdGlvbl9jb2RlIiwiaWF0IjoxNzAwMzYzMzIyfQ.IRgf6L4HsTHwgIGY_i3Af1dUnS-fLkMz8ND2r6Fgux-W7lkfQYXrpAqyEn-bUZ-L47PhaNWaLIV2bCl8Bxtbk1RhOS0-Sq8YnATkCgsSTCC5gtcZx42N67oQahoInSA4QuySdz1OAChZhlgUHRWn2bnAm07gCf7jfBdqRwCY11GcJrkR4n714tKcr5olxSDok2MJKmkbTi4VPfQXKfTYb7p-mMoqg3cr7w53IrEvQrOM94tYVJs1sUX_HGLwD99d1kRZN8SW2fMUxDsXw4hcDtnL4ktVp1rzc9tseGeu8tWzbNqQHESodOSPYqsl_SaPhuLip2FNFbStqJDc1vjnlg", + "access_token": "", + "id_token": "", "token_type": "Bearer", "expires_in": 299 } ``` - - diff --git a/docs/janssen-server/auth-server/openid-features/jarm.md b/docs/janssen-server/auth-server/openid-features/jarm.md index 2aa161db112b..5f9e87a50fc5 100644 --- a/docs/janssen-server/auth-server/openid-features/jarm.md +++ b/docs/janssen-server/auth-server/openid-features/jarm.md @@ -117,8 +117,31 @@ Typical parameters are the same as standard authorization requests, with added J - `response_type` - `scope` - `state` -- `nonce` (required for relevant OIDC/implicit-hybrid flows) - `response_mode=query.jwt|fragment.jwt|form_post.jwt|jwt` +- `code_challenge` (for Authorization Code Flow with PKCE) +- `code_challenge_method` (must be `S256`) + +For new integrations using the Authorization Code Flow, use PKCE with +`code_challenge_method=S256`. JARM protects the authorization response, +while PKCE protects the authorization code against interception and +unauthorized redemption. The client must provide the corresponding +`code_verifier` when exchanging the authorization code at the token +endpoint. + +For example: + +```text +GET https:///jans-auth/restv1/authorize? + response_type=code& + client_id=& + redirect_uri=& + scope=openid& + state=& + response_mode=query.jwt& + code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM& + code_challenge_method=S256 +``` + ### Authorization response diff --git a/docs/janssen-server/auth-server/openid-features/native-sso.md b/docs/janssen-server/auth-server/openid-features/native-sso.md index 7830f0cc0431..d72161153cd4 100644 --- a/docs/janssen-server/auth-server/openid-features/native-sso.md +++ b/docs/janssen-server/auth-server/openid-features/native-sso.md @@ -30,8 +30,17 @@ Software vendor wanting to leverage native SSO feature should build the apps so during initial user authentication, the app would send `device_sso` scope in the authorization request. -The presence of the `device_sso` scope in the authorization request would enable AS to -return `device_secret` in the token response from the token endpoint. +When the `device_sso` scope is granted, Janssen Server can generate a native SSO +device secret during the authorization-code exchange and return it in the +`device_token` field of the token response. + +For native mobile applications, use the Authorization Code Flow with PKCE +(`code_challenge_method=S256`) for initial user authentication. Include +the `device_sso` scope in the authorization request along with the +required OpenID Connect scopes. + +The client must provide the corresponding `code_verifier` when +exchanging the authorization code at the token endpoint. ## Device Secret diff --git a/docs/janssen-server/auth-server/openid-features/prompt-parameter.md b/docs/janssen-server/auth-server/openid-features/prompt-parameter.md index 28c78c505b47..9474b442128e 100644 --- a/docs/janssen-server/auth-server/openid-features/prompt-parameter.md +++ b/docs/janssen-server/auth-server/openid-features/prompt-parameter.md @@ -7,7 +7,7 @@ tags: - prompt --- -# Prompt CREATE +# Prompt parameter `prompt=create` value indicates to the AS that the client desires that the user be shown the account creation page rather than the login flow. @@ -49,20 +49,28 @@ redirect a user to the /authorize endpoint of Janssen authentication API. For example: ``` -GET https://YOUR_DOMAIN//authorize? -response_type={response_type}& -client_id={client_id}& -scope={scope}& -state={state}& -ui_locales=& -claims_locales=& -acr_values=& -redirect_uri={redirect_uri}& -prompt=none - -Basic credential user +GET https:///jans-auth/restv1/authorize? + response_type=code& + client_id=& + scope=openid& + state=& + redirect_uri=& + prompt=none& + code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM& + code_challenge_method=S256 ``` +For the Authorization Code Flow, clients should use PKCE with the `S256` +code challenge method. The client generates a `code_verifier`, includes +the derived `code_challenge` in the authorization request, and sends +the original `code_verifier` when exchanging the authorization code +at the token endpoint. + +The `prompt=none` parameter requests authentication without user +interaction. If authentication or consent requires user interaction, +the authorization server returns an appropriate error, such as +`login_required` or `consent_required`. + The **prompt=none** parameter causes Janssen to immediately send a result to the specified **redirect_uri** (callback URL) using the specified **response_mode** with one of two possible responses: success or error. @@ -107,7 +115,7 @@ end ``` ![Example 1](../../../assets/prompt_none_1.png) -Example 2: **Prompt None (Without credentials in Header)** +Example 2: **Prompt None (With credentials in Header)** ``` title Prompt None (With credentials in Header) diff --git a/docs/janssen-server/auth-server/openid-features/request-objects.md b/docs/janssen-server/auth-server/openid-features/request-objects.md index b3f0b4f0de0b..f4d96e26c02c 100644 --- a/docs/janssen-server/auth-server/openid-features/request-objects.md +++ b/docs/janssen-server/auth-server/openid-features/request-objects.md @@ -38,7 +38,9 @@ The following is a non-normative example of Request Object claims before base64u { "iss": "s6BhdRkqt3", "aud": "https://janssen.example.com", - "response_type": "code id_token", + "response_type": "code", + "code_challenge": "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM", + "code_challenge_method": "S256", "client_id": "s6BhdRkqt3", "redirect_uri": "https://client.example.org/cb", "scope": "openid", @@ -74,7 +76,7 @@ Non-normative example (line breaks in values are for display only): ```text https://janssen.example.com/jans-auth/restv1/authorize? - response_type=code%20id_token + response_type=code &client_id=s6BhdRkqt3 &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb &scope=openid @@ -115,7 +117,7 @@ Non-normative authorization request example: ```text https://janssen.example.com/jans-auth/restv1/authorize? - response_type=code%20id_token + response_type=code &client_id=s6BhdRkqt3 &request_uri=https%3A%2F%2Fclient.example.org%2Frequest.jwt %23GkurKxf5T0Y-mnPFCHqWOMiZi4VS138cQO_V7PZHAdM @@ -124,6 +126,12 @@ https://janssen.example.com/jans-auth/restv1/authorize? &scope=openid ``` +For the Authorization Code Flow, clients should use PKCE with the `S256` +code challenge method. When using a Request Object, include +`code_challenge` and `code_challenge_method` in the JWT. The client +must send the corresponding `code_verifier` when exchanging the +authorization code at the token endpoint. + Janssen additionally validates `request_uri` against the client's pre-registered `request_uris` (when configured) and against [requestUriBlockList](../../reference/json/properties/janssenauthserver-properties.md#requesturiblocklist) (for example to block `localhost`). ## Signing and Encryption diff --git a/docs/janssen-server/auth-server/tokens/oauth-refresh-tokens.md b/docs/janssen-server/auth-server/tokens/oauth-refresh-tokens.md index fc1f34bf69ef..756f41c36b89 100644 --- a/docs/janssen-server/auth-server/tokens/oauth-refresh-tokens.md +++ b/docs/janssen-server/auth-server/tokens/oauth-refresh-tokens.md @@ -10,9 +10,9 @@ tags: ## Background -Refresh tokens are an optimization that allows a client to renew an access token -without having to re-authenticate. You should not issue a refresh token to -untrusted clients, i.e. public clients. +Refresh tokens allow clients to obtain new access tokens without requiring +the user to authenticate again. Janssen Auth Server supports refresh tokens for both confidential and public +clients. ## Server properties. @@ -42,6 +42,10 @@ However if intention is to leave Refresh Token after logout, it's required to se : *Default: False* - Boolean value specifying whether to skip refreshing tokens on refreshing. By default AS always creates new Refresh Token on refresh call to Token Endpoint. This property allows to avoid (skip) new Refresh Token creation. +For public clients (`token_endpoint_auth_method=none`), a successful refresh always +returns a replacement refresh token, even when `skipRefreshTokenDuringRefreshing` is +enabled. Clients must store and use the newly returned refresh token. + `refreshTokenExtendLifetimeOnRotation` : *Default: False* - Boolean value specifying whether to extend refresh tokens on rotation. By default lifetime is not extended, expiration date is set to date of previous Refresh Token. With this property it's possible to have all further Refresh Token have fixed (extended in relation to previous Refresh Token) lifetime. @@ -55,5 +59,3 @@ To revoke a token, a client can do so via the [revocation endpoint](../endpoints ### online_access scope If `online_access` scope is present then refresh token expires when the session ends (for example via front channel logout). - - diff --git a/docs/janssen-server/auth-server/tokens/openid-id-token.md b/docs/janssen-server/auth-server/tokens/openid-id-token.md index 6caa4d3047c1..b31b65c1771f 100644 --- a/docs/janssen-server/auth-server/tokens/openid-id-token.md +++ b/docs/janssen-server/auth-server/tokens/openid-id-token.md @@ -60,12 +60,19 @@ for details. ## Obtaining an ID Token -The client may obtain an ID Token in the authorization response, from the -token endpoint, or both. Note, if you intend to use the Code Flow, and you -don't intend to validate the `c_hash` or `s_hash` values in the ID Token -returned from the authorization endpoint, don't check `id_token` in the -response_type for the authorization endpoint, as it will waste compute and -storage generating a token you don't need. +In the OpenID Connect Authorization Code Flow, the client obtains an ID Token +from the token endpoint after exchanging the authorization code. Clients +should use PKCE with the `S256` code challenge method to protect the +authorization code. + +OpenID Connect also defines Implicit and Hybrid Flows, which can return +an ID Token in the authorization response. These flows are supported for +legacy compatibility but are not recommended for new OAuth 2.1-aligned +integrations. + +For new integrations, use the Authorization Code Flow with PKCE and request +`response_type=code` rather than requesting an ID Token directly in the +authorization response. ## Validating an ID Token diff --git a/docs/janssen-server/auth-server/tokens/openid-userinfo-token.md b/docs/janssen-server/auth-server/tokens/openid-userinfo-token.md index 2ff8597ae2e3..90ef78e458a8 100644 --- a/docs/janssen-server/auth-server/tokens/openid-userinfo-token.md +++ b/docs/janssen-server/auth-server/tokens/openid-userinfo-token.md @@ -11,8 +11,24 @@ tags: ## `Userinfo` JWT An OpenID Connect client, after obtaining an access token, can present it -at the Userinfo endpoint to obtain the Userinfo JWT token. The Userinfo response -is is described in [OpenID Core 5.4.3](https://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponseValidation), and directs the developer to: +at the UserInfo endpoint to obtain a UserInfo response. The response is +returned as JSON by default, or as a JWT when signing or encryption is configured. + +Clients should send the access token to the UserInfo endpoint using the +HTTP `Authorization` header with the `Bearer` authentication scheme. + +For example: + +```http +GET /jans-auth/restv1/userinfo HTTP/1.1 +Host: +Authorization: Bearer +``` + +As part of Janssen's OAuth 2.1-aligned security changes, the UserInfo +endpoint no longer accepts access tokens through URL query parameters. + +The Userinfo response is described in [OpenID Core 5.4.3](https://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponseValidation), and directs the developer to: * Verify that the OP that responded was the intended OP through a TLS server certificate check @@ -44,9 +60,9 @@ Below is an example of the Userinfo claims for the default Jans Admin user: Domains can limit the claims released to a client from the Userinfo endpoint by associating only the OpenID scopes required by that client. You can also -define new scopes, and associate any user claims with them. Note, clients still -must request the scopes they need for an access token. For example, a client -may be authorize +define new scopes, and associate any user claims with them. Clients must request the scopes needed to access the corresponding claims. +The UserInfo response contains claims authorized for the client based on +the granted scopes and applicable authorization policies. ## Requesting individual claims diff --git a/docs/janssen-server/recipes/benchmark.md b/docs/janssen-server/recipes/benchmark.md index 70948899d1f1..44ffbacc0008 100644 --- a/docs/janssen-server/recipes/benchmark.md +++ b/docs/janssen-server/recipes/benchmark.md @@ -307,6 +307,14 @@ Create the client needed to run the test by executing the following. Make sure t #### Resource Owner Password Credentials (ROPC) flow +This benchmark exercises the legacy Resource Owner Password Credentials grant. It is +not enabled in the default supported grant types and should be used only in a test +deployment explicitly configured for this grant, not as a production recommendation. + +Before proceeding with the benchmark setup, enable the `password` grant in the +authorization server's `grantTypesSupported` configuration. Ensure that the +benchmark client is also configured to use the `password` grant. + ##### Resources needed for ROPC client jmeter test The below resources were [calculated](#kubernetes-cluster-load-test-resources) when creating the nodes above. diff --git a/docs/janssen-server/reference/json/properties/janssenauthserver-properties.md b/docs/janssen-server/reference/json/properties/janssenauthserver-properties.md index c09c6d49e856..2cc0001c644f 100644 --- a/docs/janssen-server/reference/json/properties/janssenauthserver-properties.md +++ b/docs/janssen-server/reference/json/properties/janssenauthserver-properties.md @@ -625,11 +625,13 @@ tags: ## authorizationCodeLifetime -- Description: The lifetime of the Authorization Code +- Description: The authorization code lifetime in seconds. The effective value + is capped at 600 seconds; values that are zero, negative, or greater than 600 + use the 600-second maximum. - Required: No -- Default value: None +- Default value: 60 seconds (standard installation) ## authorizationEncryptionAlgValuesSupported @@ -3421,4 +3423,3 @@ tags: - Default value: SAMEORIGIN - diff --git a/docs/script-catalog/resource_owner_password_credentials/ropc.md b/docs/script-catalog/resource_owner_password_credentials/ropc.md index 1a383448d549..8c4099bff8d3 100644 --- a/docs/script-catalog/resource_owner_password_credentials/ropc.md +++ b/docs/script-catalog/resource_owner_password_credentials/ropc.md @@ -7,6 +7,13 @@ tags: --- # Resource Owner Password Credential + +!!! warning "Legacy OAuth grant" + This catalog page documents scripts for the Resource Owner Password Credentials + grant, which is not in the default supported grant types and is not recommended for + new integrations. Use only for an existing deployment that explicitly enables the + legacy flow. + Resource Owner Password Credentials script allows modifying the behavior of Resource Owner Password Credentials Grant ([RFC 6749](https://www.rfc-editor.org/rfc/rfc6749#section-4.3)). The script is invoked after normal authentication and can either leave current result or change it - authenticate if not authenticated - it should return True and optionally set user (via `context.setUser(user)`).