spring-attic / spring-security-oauth

Support for adding OAuth1(a) and OAuth2 features (consumer and provider) for Spring web applications.
http://github.com/spring-projects/spring-security-oauth
Apache License 2.0
4.69k stars 4.05k forks source link

ADFS Token Requests require client_id to be passed #765

Open johnmcteague opened 8 years ago

johnmcteague commented 8 years ago

ADFS 3.0 requires calls to the token endpoint to pass the client_id along with code, grant_type and redirect_uri parameters.

Can this be supported?

dfcoffin commented 8 years ago

I am unfamiliar with ADFS 3.0 but section 4.1.3. Access Token Request of RFC 6749, which the spring-security-oauth library is based on states:

4.1.3. Access Token Request The client makes a request to the token endpoint by sending the following parameters using the application/x-www-form-urlencoded format per with a character encoding of UTF-8 in the HTTP request entity-body:

       grant_type
            **REQUIRED**. Value MUST be set to authorization_code.
       code
            **REQUIRED**. The authorization code received from the authorization server.
       redirect_uri
            **REQUIRED**, if the redirect_uri parameter was included in the authorization
            request as described in , and their values MUST be identical.
       client_id
            **REQUIRED**, if the client is not authenticating with the authorization server as
            described in **Section 3.2.1**.

 If the client type is confidential or the client was issued client credentials (or assigned other
 authentication requirements), the client MUST authenticate with the authorization server as
 described in **Section 3.2.1**.

 For example, the client makes the following HTTP request using TLS (with extra line breaks
 for display purposes only):
          POST /token HTTP/1.1
          Host: server.example.com
          Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
          Content-Type: application/x-www-form-urlencoded
          grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
          &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
 The authorization server MUST:

      - require client authentication for confidential clients or for any client that was
      - issued client credentials (or with other authentication requirements),
      - authenticate the client if client authentication is included,
      - ensure that the authorization code was issued to the authenticated confidential
        client, or if the client is public, ensure the code was issued to client_id in the
        request,
      - verify that the authorization code is valid, and
      - ensure that the redirect_uri parameter is present if the redirect_uri
        parameter was included in the initial authorization request as described in **Section 4.1.1**
        and if included ensure that their values are identical.
johnmcteague commented 8 years ago

Referencing your above comment:

client_id
            **REQUIRED**, if the client is not authenticating with the authorization server as
            described in **Section 3.2.1**.

In ADFS my client does not authenticate, the client_id attribute should be passed.

Looking at https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProvider.java#L243, spring-security-oauth does not attempt to add client_id.

If there is a way I can insert the client_id then that would be acceptable, but I cant see how I would alter the list of parameters being sent.

dfcoffin commented 8 years ago

RFC6749 requires the requester to provide a client_id either in the HTTPS Authorization header (as shown in my previous response) for Confidential clients or in the "authorization_code" flow request sent to the OAuth /authorize endpoint. This requirement is documented in Section 3.2.1. Client Authentication of RFC6749:

**3.2.1. Client Authentication**
     Confidential clients or other clients issued client credentials MUST authenticate with the
     authorization server as described in **Section 2.3** when making requests to the token
     endpoint. Client authentication is used for:

     - Enforcing the binding of refresh tokens and authorization codes to the client they
       were issued to. Client authentication is critical when an authorization code is
       transmitted to the redirection endpoint over an insecure channel or when the
       redirection URI has not been registered in full.

     - Recovering from a compromised client by disabling the client or changing its
       credentials, thus preventing an attacker from abusing stolen refresh tokens.
       Changing a single set of client credentials is significantly faster than revoking an
       entire set of refresh tokens.
     - Implementing authentication management best practices, which require periodic
       credential rotation. Rotation of an entire set of refresh tokens can be challenging,
       while rotation of a single set of client credentials is significantly easier.

     A client MAY use the client_id request parameter to identify itself when sending requests to
     the token endpoint. In the authorization_code grant_type request to the token endpoint,
     an unauthenticated client MUST send its client_id to prevent itself from inadvertently
     accepting a code intended for a client with a different client_id. This protects the client from
     substitution of the authentication code. (It provides no additional security for the protected
     resource.)

As explained in Section 3.2.1 client_id is used by the spring-security-oauth framework to ensure an authorization code, which is required to obtain an access token for the authorization_code flow is being issued to a registered client. Without a client_id being supplied, your implementation is creating a significant security opportunity for fraudulent use of access tokens.

Have you investigated any of the spring.io SAML implementations?