Interface TokenRequestHandlerSpi

    • Method Detail

      • authenticateUser

        String authenticateUser​(String username,
                                String password)
        Authenticate an end-user.

        This method is called only when Resource Owner Password Credentials Grant was used. Therefore, if you have no mind to support Resource Owner Password Credentials, always return null. In typical cases, you don't have to support Resource Owner Password Credentials Grant. FYI: RFC 6749 says "The authorization server should take special care when enabling this grant type and only allow it when other flows are not viable."

        Below is an example implementation using Apache Shiro.

         @Override
         public String authenticateUser(String username, String password)
         {
             // Pack the username and password into AuthenticationToken
             // which Apache Shiro's SecurityManager can accept.
             AuthenticationToken credentials =
                 new UsernamePasswordToken(username, password);
        
             try
             {
                 // Authenticate the resource owner.
                 AuthenticationInfo info =
                     SecurityUtils.getSecurityManager().authenticate(credentials);
        
                 // Get the subject of the authenticated user.
                 return info.getPrincipals().getPrimaryPrincipal().toString();
             }
             catch (AuthenticationException e)
             {
                 // Not authenticated.
                 return null;
             }
         }
        Parameters:
        username - The value of username parameter in the token request.
        password - The value of password parameter in the token request.
        Returns:
        The subject (= unique identifier) of the authenticated end-user. If the pair of username and password is invalid, null should be returned.
      • getProperties

        com.authlete.common.dto.Property[] getProperties()
        Get extra properties to associate with an access token.

        This method is expected to return an array of extra properties. The following is an example that returns an array containing one extra property.

         @Override
         public Property[] getProperties()
         {
             return new Property[] {
                 new Property("example_parameter", "example_value")
             };
         }

        Extra properties returned from this method will appear as top-level entries in a JSON response from an authorization server as shown in 5.1. Successful Response in RFC 6749.

        Keys listed below should not be used and they would be ignored on the server side even if they were used. It's because they are reserved in RFC 6749 and OpenID Connect Core 1.0.

        • access_token
        • token_type
        • expires_in
        • refresh_token
        • scope
        • error
        • error_description
        • error_uri
        • id_token

        Note that there is an upper limit on the total size of extra properties. On the server side, the properties will be (1) converted to a multidimensional string array, (2) converted to JSON, (3) encrypted by AES/CBC/PKCS5Padding, (4) encoded by base64url, and then stored into the database. The length of the resultant string must not exceed 65,535 in bytes. This is the upper limit, but we think it is big enough.

        When the value of grant_type parameter contained in the token request from the client application is authorization_code or refresh_token, extra properties are merged. Rules are as described in the table below.

        grant_type Description
        authorization_code

        If the authorization code presented by the client application already has extra properties (this happens if AuthorizationDecisionHandlerSpi.getProperties() returned extra properties when the authorization code was issued), extra properties returned by this method will be merged into the existing extra properties. Note that the existing extra properties will be overwritten if extra properties returned by this method have the same keys.

        For example, if an authorization code has two extra properties, a=1 and b=2, and if this method returns two extra properties, a=A and c=3, the resultant access token will have three extra properties, a=A, b=2 and c=3.

        refresh_token

        If the access token associated with the refresh token presented by the client application already has extra properties, extra properties returned by this method will be merged into the existing extra properties. Note that the existing extra properties will be overwritten if extra properties returned by this method have the same keys.

        Returns:
        Extra properties. If null is returned, any extra property will not be associated.
        Since:
        1.3
      • tokenExchange

        javax.ws.rs.core.Response tokenExchange​(com.authlete.common.dto.TokenResponse tokenResponse,
                                                Map<String,​Object> headers)
        Handle a token exchange request.

        This method is called when the grant type of the token request is "urn:ietf:params:oauth:grant-type:token-exchange" (but see the "NOTE 2" below). The grant type is defined in RFC 8693: OAuth 2.0 Token Exchange.

        RFC 8693 is very flexible. In other words, the specification does not define details that are necessary for secure token exchange. Therefore, implementations have to complement the specification with their own rules.

        The argument passed to this method is an instance of TokenResponse that represents a response from Authlete's /auth/token API. The instance contains information about the token exchange request such as the value of the subject_token request parameter. Implementations of this tokenExchange method are supposed to (1) validate the information based on their own rules, (2) generate a token (e.g. an access token) using the information, and (3) prepare a token response in the JSON format that conforms to Section 2.2 of RFC 8693.

        Authlete's /auth/token API performs validation of token exchange requests to some extent. Therefore, authorization server implementations don't have to repeat the same validation steps. See the JavaDoc of the TokenResponse class for details about the validation steps.

        NOTE 1: Token Exchange is supported by Authlete 2.3 and newer versions. If the Authlete server of your system is older than version 2.3, the grant type ("urn:ietf:params:oauth:grant-type:token-exchange") is not supported and so this method is never called.

        NOTE 2: Even if the grant type is "urn:ietf:params:oauth:grant-type:token-exchange", if the service is configured to support the "OpenID Connect Native SSO for Mobile Apps 1.0" specification (a.k.a. "Native SSO") and the token request complies with the specification, the nativeSso method is called instead of this tokenExchange method. Native SSO is supported in Authlete 3.0 and newer versions.

        Parameters:
        tokenResponse - A response from Authlete's /auth/token API.
        headers - HTTP headers that should be included in the token response. For example, this map may include a key-value pair consisting of the DPoP-Nonce header and a DPoP nonce value (see RFC 9449: OAuth 2.0 Demonstrating Proof of Possession (DPoP), Section 8. Authorization Server-Provided Nonce). This headers parameter was introduced in version 2.86 of authlete-java-jaxrs. This is a breaking change.
        Returns:
        A response from the token endpoint. It must conform to Section 2.2 of RFC 8693. If this method returns null, TokenRequestHandler will generate 400 Bad Request with {"error":"unsupported_grant_type"}.
        Since:
        2.47, Authlete 2.3
        See Also:
        RFC 8693 OAuth 2.0 Token Exchange
      • jwtBearer

        javax.ws.rs.core.Response jwtBearer​(com.authlete.common.dto.TokenResponse tokenResponse,
                                            Map<String,​Object> headers)
        Handle a token request that uses the grant type "urn:ietf:params:oauth:grant-type:jwt-bearer" (RFC 7523).

        This method is called when the grant type of the token request is "urn:ietf:params:oauth:grant-type:jwt-bearer". The grant type is defined in RFC 7523: JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants.

        The grant type utilizes a JWT as an authorization grant, but the specification does not define details about how the JWT is generated by whom. As a result, it is not defined in the specification how to obtain the key whereby to verify the signature of the JWT. Therefore, each deployment has to define their own rules which are necessary to determine the key for signature verification.

        The argument passed to this method is an instance of TokenResponse that represents a response from Authlete's /auth/token API. The instance contains information about the token request such as the value of the assertion request parameter. Implementations of this jwtBearer method are supposed to (1) validate the authorization grant (= the JWT specified by the assertion request parameter), (2) generate an access token, and (3) prepare a token response in the JSON format that conforms to RFC 6749.

        Authlete's /auth/token API performs validation of token requests to some extent. Therefore, authorization server implementations don't have to repeat the same validation steps. Basically, what implementations have to do is to verify the signature of the JWT. See the JavaDoc of the TokenResponse class for details about the validation steps.

        NOTE: JWT Authorization Grant is supported by Authlete 2.3 and newer versions. If the Authlete server of your system is older than version 2.3, the grant type ("urn:ietf:params:oauth:grant-type:jwt-bearer") is not supported and so this method is never called.

        Parameters:
        tokenResponse - A response from Authlete's /auth/token API.
        headers - HTTP headers that should be included in the token response. For example, this map may include a key-value pair consisting of the DPoP-Nonce header and a DPoP nonce value (see RFC 9449: OAuth 2.0 Demonstrating Proof of Possession (DPoP), Section 8. Authorization Server-Provided Nonce). This headers parameter was introduced in version 2.86 of authlete-java-jaxrs. This is a breaking change.
        Returns:
        A response from the token endpoint. It must conform to RFC 6749. If this method returns null, TokenRequestHandler will generate 400 Bad Request with {"error":"unsupported_grant_type"}.
        Since:
        2.48, Authlete 2.3
        See Also:
        RFC 7521 Assertion Framework for OAuth 2.0 Client Authentication and Authorization Grants, RFC 7523 JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants
      • nativeSso

        javax.ws.rs.core.Response nativeSso​(com.authlete.common.dto.TokenResponse tokenResponse,
                                            Map<String,​Object> headers)
        Handle a token request that complies with the "OpenID Connect Native SSO for Mobile Apps 1.0" specification (also known as "Native SSO").

        This method is called if the action parameter in the response from Authlete's /auth/token API is NATIVE_SSO. This action value is returned when one of the following condition sets is satisfied.

        1. Authorization Code Flow
          • The service's nativeSsoSupported property is set to true.
          • The service supports the openid and device_sso scopes.
          • The client is allowed to request the openid and device_sso scopes.
          • The grant type of the token request is authorization_code.
          • The authorization request preceding the token request included the openid and device_sso scopes.
        2. Refresh Token Flow
          • The service's nativeSsoSupported property is set to true.
          • The service supports the device_sso scope.
          • The client is allowed to request the device_sso scope.
          • The grant type of the token request is refresh_token.
          • The access token issued by the refresh token request still covers the device_sso scope, even if the scope coverage might have been narrowed.
          • The presented refresh token is associated with a user's authentication session. (In practice, only refresh tokens generated through the authorization code flow compliant with Native SSO can be used.)
        3. Token Exchange Flow
          • The service's nativeSsoSupported property is set to true.
          • The grant type of the token request is urn:ietf:params:oauth:grant-type:token-exchange.
          • The value of the actor_token_type request parameter is urn:openid:params:token-type:device-secret.

        Session ID

        When the action value is NATIVE_SSO, the response from the /auth/token API contains a sessionId parameter. Its value represents a user's authentication session - that is, a session ID.

        The authorization server must check whether the session ID is still valid. Note that the session ID is not a value generated by Authlete but one that was passed from the authorization server to the /auth/authorization/issue API. Therefore, Authlete does not and cannot determine whether the session ID is still valid.

        If the session ID is no longer valid, the authorization server should return an error response from the token endpoint with the error code invalid_grant.

        Device Secret

        Case 1: Device Secret in Authorization Code and Refresh Token Flows

        When the grant type is authorization_code or refresh_token, the response from the /auth/token API may contain a deviceSecret parameter. Its value represents a device secret passed from the client application as the value of the device_secret request parameter to the token endpoint. This request parameter is optional.

        When the deviceSecret parameter in the response from the /auth/token API is not null, the authorization server must check whether the device secret is valid. If the device secret is valid, the value should be passed to the /nativesso API later without modification, unless the authorization server chooses to reissue a new device secret.

        On the other hand, if the deviceSecret parameter is absent or its value is invalid, the authorization server must generate a new device secret. The new value should then be passed to the /nativesso API.

        Note that Authlete neither generates nor manages device secrets. It is the authorization server's responsibility to do so. Therefore, Authlete does not and cannot determine whether a device secret is valid.

        Case 2: Device Secret in Token Exchange Flow

        When the grant type is urn:ietf:params:oauth:grant-type:token-exchange, the response from the /auth/token API contains deviceSecret and deviceSecretHash parameters.

        The deviceSecret parameter represents the device secret presented by the client application to the token endpoint as the value of the actor_token request parameter.

        The deviceSecretHash parameter represents the device secret hash embedded as the value of the ds_hash claim in the ID token that the client application passed to the token endpoint as the value of the subject_token request parameter.

        The authorization server must verify the binding between the device secret and device secret hash. If the binding fails verification, the authorization server should return an error response from the token endpoint with the error code invalid_grant.

        Note that the Native SSO specification does not define how to compute a device secret hash value from a device secret. The specification states, "The exact binding between the ds_hash and device_secret is not specified by this profile." Therefore, the authorization server must define a rule regarding for computing the device hash value and verify the binding based on that rule. A simple example of hash computation logic is to compute the SHA-256 hash of a device secret and base64url-encode the hash.

        /nativesso API Call

        After validating the session ID, device secret, and device secret hash as necessary, the authorization server must call the /nativesso API to generate a Native SSO-compliant ID token and token response. The API expects the following request parameters.

        Parameter Description
        accessToken

        REQUIRED. If the response from the /auth/token API contains the jwtAccessToken parameter, its value must be used as the value of this accessToken request parameter to the /nativesso API. If the jwtAccessToken parameter is absent, the value of the accessToken parameter in the response from the /auth/token API should be used instead.

        The specified value is used as the value of the access_token property in the token response.

        refreshToken

        OPTIONAL. If the refreshToken parameter is present in the response from the /auth/token API, its value should be specified as the value of this refreshToken request parameter to the /nativesso API. Note that whether a refresh token is issued depends on configuration.

        The specified value is used as the value of the refresh_token property in the token response.

        deviceSecret

        REQUIRED. If the response from the /auth/token API contains the deviceSecret parameter, its value should be used as the value of this deviceSecret request parameter to the /nativesso API. The authorization server may choose to issue a new device secret; in that case, it is free to generate a new device secret and specify the new value.

        If the response from the /auth/token API does not contain the deviceSecret parameter, or if its value is invalid, the authorization server must generate a new device secret and specify it in the deviceSecret parameter to the /nativesso API.

        The specified value is used as the value of the device_secret property in the token response.

        deviceSecretHash

        RECOMMENDED. The authorization server should compute the hash value of the device secret based on its own logic and specify the computed hash as the value of this deviceSecretHash request parameter to the /nativesso API.

        When the deviceSecretHash parameter is omitted, the implementation of the /nativesso API generates the device secret hash by computing the SHA-256 hash of the device secret and encoding it with base64url. Note that this hash computation logic is not a rule defined in the Native SSO specification; rather, it is Authlete-specific fallback logic used when the deviceSecretHash parameter is omitted.

        sub

        OPTIONAL. The value of the sub claim to be embedded in the ID token. If omitted, the subject associated with the access token is used as the value of the sub claim.

        claims

        OPTIONAL. Additional claims to be embedded in the ID token. The format of this parameter must be a JSON object.

        idtHeaderParams

        OPTIONAL. Additional parameters to be embedded in the JWS header of the ID token. The format of this parameter must be a JSON object.

        idTokenAudType

        OPTIONAL. This parameter specifies the type of the aud claim in the ID token. If "array" is specified, the aud claim will be a JSON array. If "string" is specified, it will be a JSON string. If omitted, the aud claim will default to a JSON array.

        On success, the action parameter in the response from the /nativesso API is OK. In this case, the value of the responseContent parameter in the response can be used as the message body of the token response from the token endpoint. The token endpoint implementation can construct the token response as follows:

         HTTP/1.1 200 OK
         Content-Type: application/json
         Cache-Control: no-cache, no-store
        
         (Embed the value of the responseContent parameter in the response
          from the /nativesso API here)
         

        The resulting message body will look like this:

         {
           "access_token":      "(Access Token)",
           "token_type":        "(Token Type)",
           "expires_in":         (Lifetime in Seconds),
           "scope":             "(Space-separated Scopes)",
           "refresh_token":     "(Refresh Token)",
           "id_token":          "(ID Token)",
           "device_secret":     "(Device Secret)",
           "issued_token_type": "urn:ietf:params:oauth:token-type:access_token"
         }

        The issued_token_type parameter in the token response is required only in the token exchange flow, but the current implementation of the /nativesso API always embeds the parameter, even in the authorization code and refresh token flows. Since it is allowed to include any parameters in token responses, this behavior should not cause any issues.

        Parameters:
        tokenResponse - A response from Authlete's /auth/token API.
        headers - HTTP headers that should be included in the token response. For example, this map may include a key-value pair consisting of the DPoP-Nonce header and a DPoP nonce value (see RFC 9449: OAuth 2.0 Demonstrating Proof of Possession (DPoP), Section 8. Authorization Server-Provided Nonce).
        Returns:
        A response from the token endpoint. It must conform to the "OpenID Connect Native SSO for Mobile Apps 1.0" specification.
        Since:
        2.86, Authlete 3.0
        See Also:
        OpenID Connect Native SSO for Mobile Apps 1.0