2016-05-25 3 views
0

У меня есть API, который я хочу защитить с помощью OAuth2. Я уже сделал фиктивный тест с паролем grant_type, и все работает. Я могу запросить маркеры, получить доступ к защищенным конечным точкам и т. Д. Сервер действует как сервер авторизации и ресурсов.OAuth2 с защитой неявного клиента и csrf

Позже я прочитал, что должен использовать неявный тип grant_type, поскольку клиент будет javascript-приложением.

Мой клиент настроен так:

@Override 
public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {// @formatter:off 
clients 
    .inMemory().withClient("web") 
    .redirectUris("http://localhost:3000") 
    .secret("secret") 
    .authorizedGrantTypes("implicit", "refresh_token").scopes("read", "write") 
    .accessTokenValiditySeconds(3600).refreshTokenValiditySeconds(2592000); 
} 

Если я пытаюсь получить доступ к конечной точке, как это: http://localhost:8080/oauth/authorize?grant_type=implicit&client_id=web&response_type=token&redirect_uri=http%3A%2F%2Flocalhost%3A3000

Я получаю это:

{ 
    "timestamp": 1464136960414, 
    "status": 403, 
    "error": "Forbidden", 
    "message": "Expected CSRF token not found. Has your session expired?", 
    "path": "/oauth/authorize" 
} 

Как я могу иметь CSRF если это первый раз, когда я вызываю API? Если (только для тестирования) отключить CSRF, то я получаю это:

{ 
    "timestamp": 1464136840865, 
    "status": 403, 
    "error": "Forbidden", 
    "exception": "org.springframework.security.authentication.InsufficientAuthenticationException", 
    "message": "Access Denied", 
    "path": "/oauth/authorize" 
} 

Настройка клиента с паролем grant_type я могу сделать этот вызов и все работает: http://localhost:8080/oauth/token?grant_type=password&username=test&password=123 А добавив Основной заголовок авторизации с идентификатором/секретом клиента.

Чтобы уточнить, идея состоит в том, чтобы иметь этот уникальный доверенный клиент. Таким образом, пользователь должен просто вводить логин/пароль, не запрашивая у пользователя права доступа к приложению.

Извините, если это глупый вопрос. Я читаю все, что могу найти, но не могу добиться успеха.

Спасибо!

EDIT:

My Spring Security Config:

@Configuration 
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 

    @Autowired 
    private MongoDBAuthenticationProvider authenticationProvider; 

    @Autowired 
    public void globalUserDetails(final AuthenticationManagerBuilder auth) throws Exception { 
    auth.authenticationProvider(authenticationProvider); 
    } 

    @Override 
    @Bean 
    public AuthenticationManager authenticationManagerBean() throws Exception { 
    return super.authenticationManagerBean(); 
    } 
} 

Мой OAuth Config:

@Configuration 
@EnableAuthorizationServer 
public class OAuth2AuthorizationServerConfig extends  AuthorizationServerConfigurerAdapter { 

    @Autowired 
    @Qualifier("authenticationManagerBean") 
    private AuthenticationManager authenticationManager; 

    @Override 
    public void configure(final AuthorizationServerSecurityConfigurer oauthServer) throws Exception { 
     oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()"); 
    } 

    @Override 
    public void configure(final ClientDetailsServiceConfigurer clients) throws Exception { 
    clients 
    .inMemory().withClient("web") 
    .redirectUris("http://localhost:3000") 
    .secret("secret") 
    .authorizedGrantTypes("implicit", "refresh_token").scopes("read", "write") 
    .accessTokenValiditySeconds(3600).refreshTokenValiditySeconds(2592000); 
    } 

    @Override 
    public void configure(AuthorizationServerEndpointsConfigurer endpoints)  throws Exception { 
    endpoints.authenticationManager(authenticationManager); 
    } 
} 

исключений в сервере:

2016-05-25 19:52:20.744 DEBUG 34968 --- [nio-8080-exec-5] .s.o.p.e.FrameworkEndpointHandlerMapping : Looking up handler method for path /oauth/authorize 
2016-05-25 19:52:20.744 DEBUG 34968 --- [nio-8080-exec-5] .s.o.p.e.FrameworkEndpointHandlerMapping : Returning handler method [public org.springframework.web.servlet.ModelAndView org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint.authorize(java.util.Map<java.lang.String, java.lang.Object>,java.util.Map<java.lang.String, java.lang.String>,org.springframework.web.bind.support.SessionStatus,java.security.Principal)] 
2016-05-25 19:52:20.746 DEBUG 34968 --- [nio-8080-exec-5] o.s.s.w.a.ExceptionTranslationFilter  : Authentication exception occurred; redirecting to authentication entry point 

org.springframework.security.authentication.InsufficientAuthenticationException: User must be authenticated with Spring Security before authorization can be completed. 
at  org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint.authorize(AuthorizationEndpoint.java:138) ~[spring-security-oauth2-2.0.9.RELEASE.jar:na] 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_40] 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_40] 
.... 

ответ

1

При вызове сервера авторизации для неявный тип гранта, вы должны включить непрозрачное строковое значение в качестве параметра состояния, чтобы избежать атак csrf. Таким образом, URL запроса на сервер авторизации будет выглядеть следующим образом:

http://localhost:8080/oauth/authorize?grant_type=implicit&client_id=web&response_type=token&redirect_uri=http%3A%2F%2Flocalhost%3A3000&state=123abc

Значение, которое вы упомянули в состоянии параметра будет вторит обратно к вам в ответ. Затем вы сравниваете эхо-значение с начальным значением, чтобы подтвердить, что атака csrf не произошла.

Спасибо, Сома.

+0

Спасибо за ваш ответ @Soma. Я слышал о «государственном» параметре, но до сих пор не обработал его, что касается моего дела. Я изменил его, но я все еще получаю ошибки. Я выпустил его как POST, и я получаю ошибку csrf, с GET я получаю Access Denied. Я обновлю свой вопрос еще одним кодом и посмотрю, сможете ли вы обнаружить какие-либо ошибки.Большое спасибо! – user1294431

+0

Запрос должен быть GET. Просто чтобы подтвердить, вы зарегистрировали клиента? Отправьте подробное сообщение об ошибке с GET. Спасибо –

+0

Я отредактировал ответ. Большое вам спасибо за вашу помощь и время. – user1294431

Смежные вопросы