6

Background

I have a Spring application with OAuth2 security.

I can easily obtain an OAuth Bearer token with the following request:

POST {{...}}/oauth/token
?grant_type=password
&client_id={{client_id}}
&username={{username}}
&password={{password}}

This returns a 200 OK request with my access_token in the response.

Problem

My problem is that one of my clients doesn't like the idea of sending plain text passwords in the query as a query parameter and they want to get the OAuth Bearer token using Basic Autentication.

However I can't make it work the following way:

POST {{...}}/oauth/token

Authorization: Basic base64encoded(username:password)

Content-Type: application/x-www-form-urlencoded

Request Body:

{
  "grant_type": "password",
  "client_id": {{client_id}}
}

It returns 401 Unauthorized, and

{
    "error": "unauthorized",
    "error_description": "Bad credentials"
}

My applicationContext.xml file looks like this:

<beans>
...
  <!-- Definition of the Authentication Service -->
  <security:http 
    pattern="/oauth/token" 
    create-session="stateless"
    authentication-manager-ref="clientAuthenticationManager">
    <security:anonymous enabled="false"/>
    <security:http-basic entry-point-ref="clientAuthenticationEntryPoint"/>
    <security:custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER"/>
    <security:access-denied-handler ref="oauthAccessDeniedHandler"/>
  </security:http>

  <!-- Protected resources -->
  <security:http 
    pattern="/v3/**" 
    create-session="never"
    entry-point-ref="oauthAuthenticationEntryPoint"
    access-decision-manager-ref="accessDecisionManager">
    <security:anonymous enabled="false"/>
    <security:intercept-url pattern="/v3/**" access="IS_AUTHENTICATED_FULLY"/>
    <security:custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER"/>
    <security:access-denied-handler ref="oauthAccessDeniedHandler"/>
  </security:http>

  <bean id="clientAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
    <property name="typeName" value="Basic"/>
  </bean>

  <bean id="oauthAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint"/>

  <bean id="oauthAccessDeniedHandler" class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler"/>

  <bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
    <property name="authenticationManager" ref="clientAuthenticationManager"/>
  </bean>

  <bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased">
    <constructor-arg>
      <list>
        <bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter"/>
        <bean class="org.springframework.security.access.vote.RoleVoter"/>
        <bean class="org.springframework.security.access.vote.AuthenticatedVoter"/>
      </list>
    </constructor-arg>
  </bean>

  <security:authentication-manager id="clientAuthenticationManager">
    <security:authentication-provider user-service-ref="clientDetailsUserService"/>
  </security:authentication-manager>

  <bean id="clientDetailsUserService" class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
    <constructor-arg ref="clientDetails"/>
  </bean>

  <security:authentication-manager alias="authenticationManager">
    <security:authentication-provider ref="myAuthProvider"/>
  </security:authentication-manager>

  <bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore"/>

  <bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
    <property name="accessTokenValiditySeconds" value="86400"/>
    <property name="tokenStore" ref="tokenStore"/>
    <property name="supportRefreshToken" value="true"/>
    <property name="clientDetailsService" ref="clientDetails"/>
  </bean>

  <bean id="oAuth2RequestFactory" class="org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory">
    <constructor-arg ref="clientDetails"/>
  </bean>

  <oauth:authorization-server client-details-service-ref="clientDetails" token-services-ref="tokenServices">
    <oauth:authorization-code/>
    <oauth:implicit/>
    <oauth:refresh-token/>
    <oauth:password/>
  </oauth:authorization-server>

  <oauth:resource-server id="resourceServerFilter" token-services-ref="tokenServices"/>

  <oauth:client-details-service id="clientDetails">
    <oauth:client client-id="web-console"
      authorized-grant-types="password,authorization_code,refresh_token,implicit,redirect"
      authorities="ROLE_CLIENT, ROLE_TRUSTED_CLIENT"
      scope="read,write,trust"
      access-token-validity="86400"
      refresh-token-validity="86400"/>
  </oauth:client-details-service>
...
</beans>

Question

Ideally I should be able to call the /oauth/token endpoint with Authorization Basic xxxxxxxxxxxxxxx header, and I would be able to obtain the OAuth bearer token.

martoncsukas
  • 2,077
  • 20
  • 23
  • 1
    Take a look in this [answer](https://stackoverflow.com/questions/50421942/spirng-boot-2-jwt-oauth2-angular-5-cant-get-the-jwt/50422826#50422826). It describes how request format should be, hopefully you can find some useful info. – lzagkaretos Aug 03 '18 at 16:31

0 Answers0