web-dev-qa-db-fra.com

Comment changer le point de terminaison du jeton par défaut oauth2 de sécurité du printemps?

Nous avons une application basée sur oauth2 de sécurité de printemps. Tout fonctionne bien. Mais je ne parviens pas à changer le point de terminaison du jeton par défaut de "/ oauth/token" en "/ external/oauth/token".

My spring-servlet.xml

<http pattern="/external/oauth/token" create-session="stateless" 
       authentication-manager-ref="clientAuthenticationManager"
       use-expressions="true" xmlns="http://www.springframework.org/schema/security">
      <intercept-url pattern="/external/oauth/token" access="isFullyAuthenticated()" />
      <anonymous enabled="false" />
      <http-basic entry-point-ref="clientAuthenticationEntryPoint" />
      <!-- include this only if you need to authenticate clients via request parameters -->
      <custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER" />
      <access-denied-handler ref="oauthAccessDeniedHandler"/>
</http>

<oauth:authorization-server client-details-service-ref="clientDetails" 
        token-services-ref="tokenServices" 
        user-approval-handler-ref="userApprovalHandler" token-endpoint-url="/external/oauth/token">
        <oauth:authorization-code />
        <oauth:implicit />
        <oauth:refresh-token />
        <oauth:client-credentials />
        <oauth:password />
</oauth:authorization-server>

Mais le résultat quand j'accède à ce point final est

{
    error: "unauthorized"
    error_description: "An Authentication object was not found in the SecurityContext"
}

est-ce que je manque quelque chose? Veuillez suggérer.

26
Srikanth

Avec la version 2.0.5.RELEASE ou supérieure de spring-security-oauth2

Sur une ligne dans Java, testée et fonctionne correctement, elle remplace en quelque sorte la valeur RequestMapping de la classe TokenEndpoint.

@Configuration
@EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {      

        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            endpoints
                .pathMapping("/oauth/token", "<your custom endpoint>")
        }
}
32
Emilien Brigand

Je me suis juste débattu avec cela pendant quelques jours, mais il fonctionne maintenant sur la dernière version Spring Oauth2 1.0.5.RELEASE. Je ne suis pas sûr à 100% que ma solution est la plus classe (étape 4 en particulier), mais cela fonctionne et je peux aller de l'avant.

Dans mon cas, je voulais supprimer le préfixe /oauth Des URL pour finir avec seulement /token Et /authorize. La solution pour moi était principalement la configuration xml, avec deux hacks pour remplacer les mappages de demande de point de terminaison.

1 - Dans le contexte d'application xml, ajoutez les attributs authorization-endpoint-url Et token-endpoint-url À votre élément <oauth:authorization-server>.

Mien:

<oauth:authorization-server client-details-service-ref="clientDetailsService" token-services-ref="tokenServices" user-approval-handler-ref="userApprovalHandler" authorization-endpoint-url="/authorize" token-endpoint-url="/token">

2 - Dans le contexte d'application xml, ajustez les points de terminaison de sécurité en conséquence. Il devrait y en avoir deux, qui gèrent respectivement la sécurité sur les URL de jeton et d'authentification. Besoin de mettre à jour le support de modèle sur les balises <http> Et <intercept-url>.

Mien:

<http pattern="/token/**" create-session="stateless" authentication-manager-ref="clientAuthenticationManager" xmlns="http://www.springframework.org/schema/security">
    <intercept-url pattern="/token/**" access="IS_AUTHENTICATED_FULLY" />

...

<http pattern="/authorize/**" access-denied-page="/login.jsp?authorization_error=true" disable-url-rewriting="true" xmlns="http://www.springframework.org/schema/security">
    <intercept-url pattern="/authorize/**" access="IS_AUTHENTICATED_FULLY" />

3 - (Si vous avez choisi d'utiliser le filtre clientCreds facultatif.) Dans le contexte d'application xml, vous devriez déjà avoir câblé le bean clientCredentialsTokenEndpointFilter en tant que <custom-filter> within yourelement. So, within the filter's bean, add a FilterProcessesUrl` propriété.

Mien:

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

4 - La dernière étape consiste à remplacer les URL de mappage des demandes des contrôleurs de point de terminaison internes réels. La librairie spring oauth2 est livrée avec deux classes: AuthorizationEndpoint et TokenEndpoint. Chacun utilise des annotations de type @RequestMapping Pour lier l'url (comme nous le faisons tous pour les contrôleurs d'application de nos projets). Pour moi, c'était un effort époustouflant d'essayer de remplacer la valeur des mappages de demandes d'une manière autre que (malheureusement) recréer le package de classe Spring dans mon dossier src, copier les classes AuthorizationEndpoint et TokenEndpoint textuellement dans ce dossier, et modifiez les valeurs d'annotation en ligne @RequestMapping.

Quoi qu'il en soit, cela fait l'affaire. J'adorerais entendre parler d'une manière plus gracieuse de remplacer les valeurs de mappage de demande de contrôleur de point final.

Merci.

Contexte final de l'application:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:sec="http://www.springframework.org/schema/security" xmlns:oauth="http://www.springframework.org/schema/security/oauth2"

  xsi:schemaLocation="
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd
    http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2.xsd
  "
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>

  <!-- Declare OAuth2 services white-list. (This is the top of the config.) -->
  <oauth:authorization-server client-details-service-ref="clientDetailsService" token-services-ref="tokenServices" user-approval-handler-ref="userApprovalHandler" authorization-endpoint-url="/authorize" token-endpoint-url="/token">
    <oauth:authorization-code />
    <oauth:implicit />
    <oauth:refresh-token />
    <oauth:client-credentials />
    <!-- <oauth:password /> -->
  </oauth:authorization-server>
  <bean id="userApprovalHandler" class="org.springframework.security.oauth2.provider.approval.TokenServicesUserApprovalHandler">
    <!-- This bean bridges client auth service and user tokens... kind of an out of place requirement. -->
    <property name="tokenServices" ref="tokenServices" />
  </bean>

  <!-- This starts the far back-end config for client token management. -->
  <sec:authentication-manager id="clientAuthenticationManager">
    <sec:authentication-provider user-service-ref="clientDetailsUserService" />
  </sec:authentication-manager>
  <bean id="clientDetailsUserService" class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
    <constructor-arg ref="clientDetailsService" />
  </bean>
  <bean id="clientDetailsService" class="com.mycompany.oauth.spring.security.oauth2.IntegratedOauth2ClientDetailsService">
    <!-- This bean is what wires OAuth2 into the persistence stack for client details stored in the oauth_client table. -->
  </bean>


  <!-- OAuth is layered on to spring security which is centered around users which requires a user auth manager.  -->
  <authentication-manager alias="authenticationManager" xmlns="http://www.springframework.org/schema/security">
    <authentication-provider ref="daoAuthenticationProvider" />
  </authentication-manager>
  <bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
    <property name="userDetailsService" ref="userDetailsService" />
  </bean>

  <bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
    <property name="tokenStore" ref="tokenStore" />
    <property name="supportRefreshToken" value="true" />
    <property name="clientDetailsService" ref="clientDetailsService" />
  </bean>
  <bean id="tokenStore" class="com.mycompany.oauth.spring.security.oauth2.IntegratedOAuth2TokenStore">
    <!-- This bean is what wires OAuth2 tokens into my company's application stack. -->
    <constructor-arg ref="dataSource" />
  </bean>

  <!-- **************************************************************************************** -->
  <!-- Finally, sew OAuth into spring security with some http tags... -->
  <!-- **************************************************************************************** -->

  <!-- The OAuth2 endpoint for direct token requests (i.e. for client_credentials flow). -->
  <http pattern="/token/**" create-session="stateless" authentication-manager-ref="clientAuthenticationManager" xmlns="http://www.springframework.org/schema/security">
    <intercept-url pattern="/token/**" access="IS_AUTHENTICATED_FULLY" />
    <anonymous enabled="false" />
    <http-basic entry-point-ref="clientAuthenticationEntryPoint" />
    <custom-filter ref="clientCredentialsTokenEndpointFilter" before="BASIC_AUTH_FILTER" />
    <access-denied-handler ref="oauthAccessDeniedHandler" />
  </http>
  <bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
    <property name="authenticationManager" ref="clientAuthenticationManager" />
    <property name="filterProcessesUrl" value="/token" />
  </bean>
  <bean id="clientAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
    <property name="realmName" value="myrealm" />
  </bean>
  <bean id="oauthAccessDeniedHandler" class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />

  <!-- The OAuth2 endpoint for user-approved authorization (i.e. for "authorization" flow involving user login/approve). -->
  <http pattern="/authorize/**" access-denied-page="/login.jsp?authorization_error=true" disable-url-rewriting="true" xmlns="http://www.springframework.org/schema/security">
    <intercept-url pattern="/authorize/**" access="IS_AUTHENTICATED_FULLY" />
    <form-login authentication-failure-url="/login.jsp?authentication_error=true" default-target-url="http://www.mycompany.com/" login-page="/login.jsp" login-processing-url="/login.do" />
    <http-basic />
    <anonymous />
  </http>

</beans>
6
Steven Francolla

Pour personnaliser l'URL du point de terminaison du jeton, procédez comme suit.

1) Écrivez votre propre classe qui étend la classe ClientCredentialsTokenEndpointFilter et appelez le constructeur de classe ClientCredentialsTokenEndpointFilter avec la valeur "/ external/oauth/token".

super("/external/oauth/token");

2) Branchez votre nouveau filtre personnalisé dans la configuration de sécurité.

Remplacer

<custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER" />

avec

<custom-filter ref="your customize filter" after="BASIC_AUTH_FILTER" />

3) Créez votre propre classe pour un nouveau mappage (/ external/oauth/token) et étendez tokenendpoint.

4) Modifiez la valeur d'attribut de modèle de l'élément http & intercept-url en "/ external/oauth/token"

4
Anurag

Vous rendez cela plus difficile que ce qu'il devrait être, c'est en fait très simple! (Notez que j'utilise "oauth2:" au lieu de "oauth:" comme balise XML)

  1. Accédez à votre security-context.xml

  2. Recherchez "oauth2: serveur d'autorisation" dans le fichier ci-dessus.

    <oauth2:authorization-server
                    client-details-service-ref="someService"
                    request-validator-ref="someScopeRequestValidator"
                    token-services-ref="someTokenServices" >
    
  3. Ajoutez simplement token-endpoint-url="/oauth/whatever_you_like"

    <oauth2:authorization-server
                    client-details-service-ref="someService"
                    request-validator-ref="someScopeRequestValidator"
                    token-services-ref="someTokenServices" 
    **token-endpoint-url="/oauth/whatever_you_like"** >
    
4
grepit