keycloak-scim/docs/documentation/server_admin/topics/sso-protocols/con-oidc-auth-flows.adoc

370 lines
20 KiB
Text
Raw Normal View History

2020-12-16 22:48:27 +00:00
[id="con-oidc-auth-flows_{context}"]
==== OIDC auth flows
[role="_abstract"]
OIDC has several methods, or flows, that clients or applications can use to authenticate users and receive _identity_ and _access_ tokens. The method depends on the type of application or client requesting access.
[[_oidc-auth-flows-authorization]]
===== Authorization Code Flow
The Authorization Code Flow is a browser-based protocol and suits authenticating and authorizing browser-based applications. It uses browser redirects to obtain _identity_ and _access_ tokens.
. A user connects to an application using a browser. The application detects the user is not logged into the application.
. The application redirects the browser to {project_name} for authentication.
. The application passes a callback URL as a query parameter in the browser redirect. {project_name} uses the parameter upon successful authentication.
. {project_name} authenticates the user and creates a one-time, short-lived, temporary code.
. {project_name} redirects to the application using the callback URL and adds the temporary code as a query parameter in the callback URL.
. The application extracts the temporary code and makes a background REST invocation to {project_name}
to exchange the code for an _identity_ and _access_ and _refresh_ token. To prevent replay attacks, the temporary code cannot be used more than once.
[NOTE]
====
A system is vulnerable to a stolen token for the lifetime of that token. For security and scalability reasons, access tokens are generally set to expire quickly so subsequent token requests fail. If a token expires, an application can obtain a new access token using the additional _refresh_ token sent by the login protocol.
====
[[_confidential-clients]]
_Confidential_ clients provide client secrets when they exchange the temporary codes for tokens. _Public_ clients are not required to provide client secrets.
_Public_ clients are secure when HTTPS is strictly enforced and redirect URIs registered for the client are strictly controlled. HTML5/JavaScript clients have to be _public_ clients because there is no way to securely transmit the client secret to HTML5/JavaScript clients. For more details, see the xref:assembly-managing-clients_{context}[Managing Clients] chapter.
{project_name} also supports the https://datatracker.ietf.org/doc/html/rfc7636[Proof Key for Code Exchange] specification.
[[_oidc-auth-flows-implicit]]
===== Implicit Flow
The Implicit Flow is a browser-based protocol. It is similar to the Authorization Code Flow but with fewer requests and no refresh tokens.
[NOTE]
====
The possibility exists of _access_ tokens leaking in the browser history when tokens are transmitted via redirect URIs (see below).
Also, this flow does not provide clients with refresh tokens. Therefore, access tokens have to be long-lived or users have to re-authenticate when they expire.
We do not advise using this flow. This flow is supported because it is in the OIDC and OAuth 2.0 specification.
====
The protocol works as follows:
. A user connects to an application using a browser. The application detects the user is not logged into the application.
. The application redirects the browser to {project_name} for authentication.
. The application passes a callback URL as a query parameter in the browser redirect. {project_name} uses the query parameter upon successful authentication.
. {project_name} authenticates the user and creates an _identity_ and _access_ token. {project_name}
redirects to the application using the callback URL and additionally adds the _identity_ and _access_ tokens as a query parameter in the callback URL.
. The application extracts the _identity_ and _access_ tokens from the callback URL.
[[_oidc-auth-flows-direct]]
===== Resource owner password credentials grant (Direct Access Grants)
_Direct Access Grants_ are used by REST clients to obtain tokens on behalf of users. It is a HTTP POST request that contains:
* The credentials of the user. The credentials are sent within form parameters.
* The id of the client.
* The clients secret (if it is a confidential client).
The HTTP response contains the _identity_, _access_, and _refresh_ tokens.
[[_client_credentials_grant]]
===== Client credentials grant
The _Client Credentials Grant_ creates a token based on the metadata and permissions of a service account associated with the client instead of obtaining a token that works on behalf of an external user. _Client Credentials Grants_ are used by REST clients.
See the <<_service_accounts,Service Accounts>> chapter for more information.
[[_refresh_token_grant]]
===== Refresh token grant
By default, {project_name} returns refresh tokens in the token responses from most of the flows. Some exceptions are implicit flow or client credentials grant described above.
Refresh token is tied to the user session of the SSO browser session and can be valid for the lifetime of the user session. However, that client should send a refresh-token request at least once per
specified interval. Otherwise, the session can be considered "idle" and can expire. See the <<_timeouts,timeouts section>> for more information.
{project_name} supports <<_offline-access,offline tokens>>, which can be used typically when client needs to use refresh token even if corresponding browser SSO session is already expired.
[[_refresh_token_rotation]]
====== Refresh token rotation
It is possible to specify that the refresh token is considered invalid once it is used. This means that client must always save the refresh token from the last refresh response because older refresh tokens,
which were already used, would not be considered valid anymore by {project_name}. This is possible to set with the use of _Revoke Refresh token_ option as specified in the <<_timeouts,timeouts section>>.
{project_name} also supports the situation that no refresh token rotation exists. In this case, a refresh token is returned during login, but subsequent responses from refresh-token requests will not
return new refresh tokens. This practice is recommended for instance in the *FAPI 2 draft specification* in the link:{securing_apps_link}[securing apps] section.
In {project_name}, it is possible to skip refresh token rotation with the use of <<_client_policies,client policies>>. You can add executor `suppress-refresh-token-rotation` to some client
profile and configure client policy to specify for which clients would be the profile triggered, which means that for those clients the refresh token rotation is going to be skipped.
===== Device authorization grant
This is used by clients running on internet-connected devices that have limited input capabilities or lack a suitable browser. Here's a brief summary of the protocol:
. The application requests {project_name} a device code and a user code. {project_name} creates a device code and a user code. {project_name} returns a response including the device code and the user code to the application.
. The application provides the user with the user code and the verification URI. The user accesses a verification URI to be authenticated by using another browser. You could define a short verification_uri that will be redirected to {project_name} verification URI (/realms/realm_name/device)outside {project_name} - fe in a proxy.
2021-04-20 15:41:02 +00:00
. The application repeatedly polls {project_name} to find out if the user completed the user authorization. If user authentication is complete, the application exchanges the device code for an _identity_, _access_ and _refresh_ token.
[[_client_initiated_backchannel_authentication_grant]]
===== Client initiated backchannel authentication grant
2021-04-20 15:41:02 +00:00
This feature is used by clients who want to initiate the authentication flow by communicating with the OpenID Provider directly without redirect through the user's browser like OAuth 2.0's authorization code grant. Here's a brief summary of the protocol:
2021-04-20 15:41:02 +00:00
. The client requests {project_name} an auth_req_id that identifies the authentication request made by the client. {project_name} creates the auth_req_id.
. After receiving this auth_req_id, this client repeatedly needs to poll {project_name} to obtain an Access Token, Refresh Token and ID Token from {project_name} in return for the auth_req_id until the user is authenticated.
2021-04-20 15:41:02 +00:00
An administrator can configure Client Initiated Backchannel Authentication (CIBA) related operations as `CIBA Policy` per realm.
Also please refer to other places of {project_name} documentation like *Backchannel Authentication Endpoint* and *Client Initiated Backchannel Authentication Grant* in the link:{securing_apps_link}[securing apps] section.
2021-04-20 15:41:02 +00:00
====== CIBA Policy
An administrator carries out the following operations on the `Admin Console` :
- Open the `Authentication -> CIBA Policy` tab.
- Configure items and click `Save`.
The configurable items and their description follow.
|===
|Configuration|Description
|Backchannel Token Delivery Mode
|Specifying how the CD (Consumption Device) gets the authentication result and related tokens. There are three modes, "poll", "ping" and "push". {project_name} only supports "poll". The default setting is "poll". This configuration is required.
For more details, see https://openid.net/specs/openid-client-initiated-backchannel-authentication-core-1_0.html#rfc.section.5[CIBA Specification].
|Expires In
|The expiration time of the "auth_req_id" in seconds since the authentication request was received. The default setting is 120. This configuration is required.
For more details, see https://openid.net/specs/openid-client-initiated-backchannel-authentication-core-1_0.html#successful_authentication_request_acknowdlegment[CIBA Specification].
|Interval
|The interval in seconds the CD (Consumption Device) needs to wait for between polling requests to the token endpoint. The default setting is 5. This configuration is optional.
For more details, see https://openid.net/specs/openid-client-initiated-backchannel-authentication-core-1_0.html#successful_authentication_request_acknowdlegment[CIBA Specification].
|Authentication Requested User Hint
|The way of identifying the end-user for whom authentication is being requested. The default setting is "login_hint". There are three modes, "login_hint", "login_hint_token" and "id_token_hint". {project_name} only supports "login_hint". This configuration is required.
For more details, see https://openid.net/specs/openid-client-initiated-backchannel-authentication-core-1_0.html#rfc.section.7.1[CIBA Specification].
|===
====== Provider Setting
The CIBA grant uses the following two providers.
. Authentication Channel Provider : provides the communication between {project_name} and the entity that actually authenticates the user via AD (Authentication Device).
. User Resolver Provider : get `UserModel` of {project_name} from the information provided by the client to identify the user.
{project_name} has both default providers. However, the administrator needs to set up Authentication Channel Provider like this:
[source,bash,subs="attributes+"]
----
kc.[sh|bat] start --spi-ciba-auth-channel-ciba-http-auth-channel-http-authentication-channel-uri=https://backend.internal.example.com{kc_base_path}
----
2021-04-20 15:41:02 +00:00
The configurable items and their description follow.
|===
|Configuration|Description
|http-authentication-channel-uri
2021-04-20 15:41:02 +00:00
|Specifying URI of the entity that actually authenticates the user via AD (Authentication Device).
|===
====== Authentication Channel Provider
CIBA standard document does not specify how to authenticate the user by AD. Therefore, it might be implemented at the discretion of products. {project_name} delegates this authentication to an external authentication entity. To communicate with the authentication entity, {project_name} provides Authentication Channel Provider.
Its implementation of {project_name} assumes that the authentication entity is under the control of the administrator of {project_name} so that {project_name} trusts the authentication entity. It is not recommended to use the authentication entity that the administrator of {project_name} cannot control.
Authentication Channel Provider is provided as SPI provider so that users of {project_name} can implement their own provider in order to meet their environment. {project_name} provides its default provider called HTTP Authentication Channel Provider that uses HTTP to communicate with the authentication entity.
If a user of {project_name} user want to use the HTTP Authentication Channel Provider, they need to know its contract between {project_name} and the authentication entity consisting of the following two parts.
Authentication Delegation Request/Response::
2021-04-20 15:41:02 +00:00
{project_name} sends an authentication request to the authentication entity.
Authentication Result Notification/ACK::
2021-04-20 15:41:02 +00:00
The authentication entity notifies the result of the authentication to {project_name}.
Authentication Delegation Request/Response consists of the following messaging.
Authentication Delegation Request:: The request is sent from {project_name} to the authentication entity to ask it for user authentication by AD.
----
POST [delegation_reception]
----
* Headers
|===
|Name|Value|Description
|Content-Type|application/json|The message body is json formatted.
|Authorization|Bearer [token]|The [token] is used when the authentication entity notifies the result of the authentication to {project_name}.
|===
* Parameters
|===
|Type|Name|Description
|Path
|delegation_reception|The endpoint provided by the authentication entity to receive the delegation request
|===
* Body
|===
|Name|Description
|login_hint|It tells the authentication entity who is authenticated by AD. +
By default, it is the user's "username". +
This field is required and was defined by CIBA standard document.
|scope|It tells which scopes the authentication entity gets consent from the authenticated user. +
This field is required and was defined by CIBA standard document.
|is_consent_required|It shows whether the authentication entity needs to get consent from the authenticated user about the scope. +
This field is required.
|binding_message|Its value is intended to be shown in both CD and AD's UI to make the user recognize that the authentication by AD is triggered by CD. +
This field is optional and was defined by CIBA standard document.
|acr_values|It tells the requesting Authentication Context Class Reference from CD. +
This field is optional and was defined by CIBA standard document.
|===
Authentication Delegation Response:: The response is returned from the authentication entity to {project_name} to notify that the authentication entity received the authentication request from {project_name}.
* Responses
|===
|HTTP Status Code|Description
|201|It notifies {project_name} of receiving the authentication delegation request.
|===
Authentication Result Notification/ACK consists of the following messaging.
Authentication Result Notification:: The authentication entity sends the result of the authentication request to {project_name}.
[source,subs=+attributes]
2021-04-20 15:41:02 +00:00
----
POST {kc_realms_path}/[realm]/protocol/openid-connect/ext/ciba/auth/callback
2021-04-20 15:41:02 +00:00
----
* Headers
|===
|Name|Value|Description
|Content-Type|application/json|The message body is json formatted.
|Authorization|Bearer [token]|The [token] must be the one the authentication entity has received from {project_name} in Authentication Delegation Request.
|===
* Parameters
|===
|Type|Name|Description
|Path
|realm|The realm name
|===
* Body
|===
|Name|Description
|status|It tells the result of user authentication by AD. +
It must be one of the following status. +
SUCCEED : The authentication by AD has been successfully completed. +
UNAUTHORIZED : The authentication by AD has not been completed. +
CANCELLED : The authentication by AD has been cancelled by the user.
|===
Authentication Result ACK:: The response is returned from {project_name} to the authentication entity to notify {project_name} received the result of user authentication by AD from the authentication entity.
* Responses
|===
|HTTP Status Code|Description
|200|It notifies the authentication entity of receiving the notification of the authentication result.
|===
====== User Resolver Provider
Even if the same user, its representation may differ in each CD, {project_name} and the authentication entity.
For CD, {project_name} and the authentication entity to recognize the same user, this User Resolver Provider converts their own user representations among them.
User Resolver Provider is provided as SPI provider so that users of {project_name} can implement their own provider in order to meet their environment. {project_name} provides its default provider called Default User Resolver Provider that has the following characteristics.
* Only support `login_hint` parameter and is used as default.
* `username` of UserModel in {project_name} is used to represent the user on CD, {project_name} and the authentication entity.
[[_oidc-logout]]
==== OIDC Logout
OIDC has four specifications relevant to logout mechanisms:
. https://openid.net/specs/openid-connect-session-1_0.html[Session Management]
. https://openid.net/specs/openid-connect-rpinitiated-1_0.html[RP-Initiated Logout]
. https://openid.net/specs/openid-connect-frontchannel-1_0.html[Front-Channel Logout]
. https://openid.net/specs/openid-connect-backchannel-1_0.html[Back-Channel Logout]
Again since all of this is described in the OIDC specification we will only give a brief overview here.
===== Session Management
This is a browser-based logout. The application obtains session status information from {project_name} at a regular basis.
When the session is terminated at {project_name} the application will notice and trigger its own logout.
===== RP-Initiated Logout
This is also a browser-based logout where the logout starts by redirecting the user to a specific endpoint at {project_name}.
This redirect usually happens when the user clicks the `Log Out` link on the page of some application, which previously used {project_name} to authenticate the user.
Once the user is redirected to the logout endpoint, {project_name} is going to send logout requests to
clients to let them invalidate their local user sessions, and potentially redirect the user to some URL
once the logout process is finished. The user might be optionally requested to confirm the logout in case the `id_token_hint` parameter was not used.
After logout, the user is automatically redirected to the specified `post_logout_redirect_uri` as long as it is provided as a parameter.
Note that you need to include either the `client_id` or `id_token_hint` parameter in case the `post_logout_redirect_uri` is included. Also the `post_logout_redirect_uri` parameter
needs to match one of the `Valid Post Logout Redirect URIs` specified in the client configuration.
Depending on the client configuration, logout requests can be sent to clients through the front-channel or through the back-channel. For the frontend browser clients, which rely on the
Session Management described in the previous section, {project_name} does not need to send any logout requests to them; these clients automatically detect that SSO session
in the browser is logged out.
===== Front-channel Logout
To configure clients to receive logout requests through the front-channel, look at the <<_front-channel-logout, Front-Channel Logout>> client setting. When using this method, consider the following:
* Logout requests sent by {project_name} to clients rely on the browser and on embedded `iframes` that are rendered for the logout page.
* By being based on `iframes`, front-channel logout might be impacted by Content Security Policies (CSP) and logout requests might be blocked.
* If the user closes the browser prior to rendering the logout page or before logout requests are actually sent to clients, their sessions at
the client might not be invalidated.
[NOTE]
====
Consider using Back-Channel Logout as it provides a more reliable and secure approach to log out users and terminate their sessions
on the clients.
====
If the client is not enabled with front-channel logout, then {project_name} is going to try first to send logout requests through the back-channel
using the <<_back-channel-logout-url, Back-Channel Logout URL>>. If not defined, the server is going to fall back to using the <<_admin-url, Admin URL>>.
===== Backchannel Logout
This is a non-browser-based logout that uses direct backchannel communication between {project_name} and clients.
{project_name} sends a HTTP POST request containing a logout token to all clients logged into {project_name}. These
requests are sent to a registered backchannel logout URLs at {project_name} and are supposed to trigger a logout at client side.