Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
projects:member_portal:oauth [2025/10/06 16:20] – created samp20projects:member_portal:oauth [2025/10/13 12:14] (current) samp20
Line 3: Line 3:
 ===== Capturing the request ===== ===== Capturing the request =====
  
-^ Column ^ Type ^ Description ^ +^ Column ^ Type ^ Obtained from ^ Description ^ 
-| id | UUID | ID to keep track of the request | +| id | UUID | Generated | ID to keep track of the request | 
-secret | str | Secret stored in a flow cookie | +token_hash | str | Generated | Hash of a secret token stored in a flow cookie | 
-| session_id | Optional FK | Associated login session | +| session_id | Optional FK | Logged in session | Associated login session | 
-| client_id | FK | The OAuth client sending this request |+| 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.
  • projects/member_portal/oauth.1759767653
  • Last modified: 2 months ago
  • by samp20