====== OAuth ====== ===== Capturing the request ===== ^ Column ^ Type ^ Obtained from ^ Description ^ | id | UUID | Generated | ID to keep track of the request | | token_hash | str | Generated | Hash of a secret token stored in a flow cookie | | session_id | Optional FK | Logged in session | Associated login session | | client_id | FK | Query string | The OAuth client sending this request | | response_type | str | Query string | OAuth response type. e.g. Authorization Code, ID token etc. | | scope | str | Query string | The requested scope. Usually contains openid as a minimum | | state | str | Query string | Client specific state | | nonce | str | Query string | Passed through to the ID token | | redirect_uri | str | Query string | Where to redirect after authenticating | | acr_values | str | Query string | Requested authentication level | | code_challenge | str | Query string | PKCE challenge | | code_challenge_method | str | Query string | PKCE method | ===== Generating the response ===== The response is dependent on the ''response_type'' field. This is a space separated set with various options: * ''code'': a code to be submitted to the Token endpoint to obtain other information. * ''token'': an access token. * ''id_token'': an OpenID ID token. The ''response_mode'' is determined implicitly based on the ''response_type''. This can take the following values: * ''query'': the response is returned in the query string. * ''fragment'': the response is returned in the URL fragment (stuff after the ''#'' symbol). The ''query'' mode is used when only the ''code'' is being requested, otherwise the URL fragment is used. Most of the time clients will only be requesting a code. ==== The authorization code ==== This is a short lived code that can be submitted to the Authorization endpoint in exchange for ID and access tokens. The ''code_challenge'' may also be used at this point using the [[https://www.rfc-editor.org/rfc/rfc7636|PKCE standard]] ==== The ID token ==== The ID token shall be returned if the ''openid'' scope was requested. These are the claims we plan to support: ^ Claim ^ Required ^ Description ^ Obtained from ^ | iss | REQUIRED | Issuer identtifier. | Portal base URL. | | sub | REQUIRED | Subject identifier. | User from the ''session_id''. | | aud | REQUIRED | Audience(s) the ID token is intended for. | ''client_id''. | | exp | REQUIRED | Token expiration time. | Per-client configuration. | | iat | REQUIRED | When the token was issued. | Current time when the token is generated. | | auth_time | OPTIONAL (unless requested through ''max_age'' query parameter) | Time when end user authentication occured. | Most recent timestamp in the session's last_xx_auth fields. | | nonce | OPTIONAL unless present in request | String value to associate client session with ID token and to mitigate replay attacks. | Request ''nonce''. | | acr | OPTIONAL unless requested by ''acr_values'' | Authentication context class (how "strong" the authentication was). | [[projects:member_portal:session|Session]] authentication level. | | amr | OPTIONAL | Authentication methods. | [[projects:member_portal:session|Session]] authentication methods based on ''last_xx_auth'' fields. May be filtered based on ''max_age'' if present. | Note that only ''azp'' is missing from the OpenID core spec as we don't plan to use any extensions to the spec. ==== The access and refresh tokens ==== While the Hackspace services might be spread across multiple servers, we will use a single logical API approach for our access tokens. This means that all scopes will be part of a single global namespace. For example ''email:send'' might allow sending emails via and email service. The Access token will be a transparent signed JWT with the following claims: ^ Claim ^ Description ^ Obtained from ^ | iss | Issuer of the token | The portal base URL | | sub | Subject | The user or client subject depending on whether it was a Authorization Code flow, or Client Credentials | | aud | The global scope namespace | Configuration value e.g. ''hackspace'' | | exp | Expiry | Relatively short configuration value e.g. 1 hour | | iat | Issued at | Timestamp when the token was created | | jti | Unique identifier | Randomly generated | | client_id | Client identifier | The OAuth client that requested the token | | scope | Granted scopes | Requested scopes filtered by the user's permissions | The refresh token will be an opaque token with a corresponding table containing the same information as the access token. The table may also contain a reference to the user's session ID so the token can be revoked if the session ends.