2017-01-10 1 views
2

Я нашел аналогичный issue, но он остался без ответа, поэтому я предполагаю, что я немного продублирую вопрос.Spring OAuth2: поддержка auth и доступа к ресурсам как с SSO, так и с пользовательским сервером auth

Я использую Spring OAuth2 для реализации отдельных ресурсов и пользовательских серверов аутентификации. Я уже настроил взаимодействие с сервером auth, выпуская &, проверяя токены JWT, и все кажется прекрасным.

Теперь я пытаюсь добавить функциональность SSO, но действительно застрял с ней. Я исследовал официальную весну examples и вложенную инструкцию, но она очень коротко сформулирована, когда речь идет о подключении части SSO к пользовательской аутентификации сервера. И на самом деле автор использует только внешний ресурс поставщика («пользовательская информация»), чтобы показать процесс.

Я думаю, что это нормальная вещь, чтобы иметь все эти средства SSO аутентификации, а также пользовательскую регистрацию. Я вижу, что он хорошо работает с stackoverflow, например.

Я собираюсь найти маршруты, где можно найти любую информацию об обработке на сервере ресурсов различных типов токенов, выданных мультиплексированными провайдерами единого входа, а также из пользовательского сервера auth. Возможно, я могу использовать цепочку auth для этого, а некоторые означают, чтобы различать формат токена, чтобы знать, как его обрабатывать. Возможно ли это с помощью Spring OAuth2? Или мне нужно сделать эту магию как-то вручную?

На данный момент у меня есть только одна «странная» идея: Не использовать мой собственный сервер ресурсов с этим материалом SSO вообще. После получения маркера Facebook (например) - просто обменять его на апи JWT лексемы с пользовательскими аутентификации сервера (ассоциирования или создание пользователя на пути), а затем работать с сервером ресурсов на стандартных основ

Редакцией: Я нашел хоть что-то. Я читал о настройке фильтров в цепочке авторизации и переводе данных социальных токенов на мои пользовательские JWT-ы как «пост-аутентификация» (а не сумасшедшая идея). Но в основном это делается с помощью SpringSocial. Итак, теперь вопрос: как это сделать? Забыл сказать, что я использую Password Grant для аутентификации на настраиваемом сервере. Клиенты будут только доверенным приложением, и я даже не уверен о клиенте браузера (думая только о собственных мобильных опциях). Даже если я решаю, что у меня будет клиент браузера, я буду уверен, что у него будет бэкэнд для хранения информации о sencetive.

ответ

2

Хорошо, поэтому, пытаясь реализовать такое поведение, я придерживался двух разных библиотек (Spring Social & OAuth2). Я решил пойти своим путем и делать это только с весны OAuth2:

  • У меня есть сервер ресурса, сервер аутентификации и клиент (подкрепленные Java и использует библиотеку Client OAuth2, но это может быть любой другой клиент) - мои ресурсы могут потребляться только с помощью моего собственного токена аутентификации JWT, предоставленного моим собственным сервером auth

  • в случае пользовательской регистрации: клиент получает токен JWT (с токеном обновления) с сервера auth и отправляет его на res сервер. Сервер Result проверяет его с помощью открытого ключа и возвращает ресурс

  • в случае единого входа: клиент получает Facebook (или другой токен социальной платформы) и обменивает его на свой пользовательский токен JWT с моим пользовательским сервером auth. Я реализовал это на своем сервере auth, используя пользовательский SocialTokenGranter (в настоящее время работает только с токеном facebook). Для каждой социальной сети мне нужен отдельный тип гранта). Этот класс делает дополнительный вызов серверу facebook auth для проверки токена и получения информации о пользователе.Затем он извлекает социального пользователя из моего db или создает новое и возвращает токен JWT обратно клиенту. Никакое слияние пользователей уже сделано. на данный момент он недоступен.

    public class SocialTokenGranter extends AbstractTokenGranter { 
    
    private static final String GRANT_TYPE = "facebook_social";  
    GiraffeUserDetailsService giraffeUserDetailsService; // custom UserDetails service 
    
    SocialTokenGranter(
         GiraffeUserDetailsService giraffeUserDetailsService, 
         AuthorizationServerTokenServices tokenServices, 
         OAuth2RequestFactory defaultOauth2RequestFactory, 
         ClientDetailsService clientDetailsService) { 
        super(tokenServices, clientDetailsService, defaultOauth2RequestFactory, GRANT_TYPE); 
        this.giraffeUserDetailsService = giraffeUserDetailsService; 
    } 
    
    @Override 
    protected OAuth2Authentication getOAuth2Authentication(ClientDetails clientDetails, TokenRequest request) { 
    
        // retrieve social token sent by the client 
        Map<String, String> parameters = request.getRequestParameters(); 
        String socialToken = parameters.get("social_token"); 
    
        //validate social token and receive user information from external authentication server 
        String url = "https://graph.facebook.com/me?access_token=" + socialToken; 
    
        Authentication userAuth = null; 
        try {  
         ResponseEntity<FacebookUserInformation> response = new RestTemplate().getForEntity(url, FacebookUserInformation.class); 
    
         if (response.getStatusCode().is4xxClientError()) throw new GiraffeException.InvalidOrExpiredSocialToken(); 
    
         FacebookUserInformation userInformation = response.getBody(); 
         GiraffeUserDetails giraffeSocialUserDetails = giraffeUserDetailsService.loadOrCreateSocialUser(userInformation.getId(), userInformation.getEmail(), User.SocialProvider.FACEBOOK); 
    
         userAuth = new UsernamePasswordAuthenticationToken(giraffeSocialUserDetails, "N/A", giraffeSocialUserDetails.getAuthorities()); 
        } catch (GiraffeException.InvalidOrExpiredSocialToken | GiraffeException.UnableToValidateSocialUserInformation e) {    
         // log the stacktrace 
        } 
        return new OAuth2Authentication(request.createOAuth2Request(clientDetails), userAuth); 
    } 
    
    private static class FacebookUserInformation { 
        private String id; 
        private String email; 
    
        // getters, setters, constructor 
    }  
    

    }

А из класса расширения AuthorizationServerConfigurerAdapter:

private TokenGranter tokenGranter(AuthorizationServerEndpointsConfigurer endpoints) { 
     List<TokenGranter> granters = new ArrayList<>(Arrays.asList(endpoints.getTokenGranter())); 
     granters.add(new SocialTokenGranter(giraffeUserDetailsService, endpoints.getTokenServices(), endpoints.getOAuth2RequestFactory(), endpoints.getClientDetailsService())); 
     return new CompositeTokenGranter(granters); 
    } 

@Override 
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { 
    oauthServer 
      ... 
      .allowFormAuthenticationForClients() // to allow sending parameters as form fields 
      ... 

} 

Каждый JWT маркер запроса будет 'хост: порт +/OAuth/маркер' URL В зависимости от ' Тип гранта 'сервер будет обрабатывать такие запросы по-разному. В настоящее время у меня есть 'пароль' (по умолчанию), 'refresh_token' и 'facebook_social' (пользовательских) типов грантов

По умолчанию 'пароль' Grant типа клиент должен отправить следующие параметры:

  • ClientId

  • clientSecret (зависит от типа клиента. Не для клиентов одной страницы)

  • имя пользователя

  • пароль

  • область видимости (если явно не установлен в конфигурации сервера Идента для текущего клиента)

  • grantType

Для 'refresh_token' Grant типа клиента должен отправить следующие параметры:

  • customerId

  • clientSecret (зависит от типа клиента. Не для клиентов одной страницы)

  • refresh_token

  • grantType

Для 'facebook_social Грант типа клиент должен отправить следующие параметры:

  • ClientId

  • facebook_social_tok еп (пользовательские поля)

  • grantType

    на основе клиента разработать способ отправить эти запросы будут отличаться. В моем случае с тестовым Java-клиентом, который использует библиотеку Spring OAuth2 для получения социального токена, я выполняю процедуру обмена токенами с перенаправлением в контроллере (контроллер вызывается с использованием url, определенного в конфигурации страницы facebook dev).

    Его можно обрабатывать в два этапа: после получения социальной токены facebook JavaScript может сделать отдельный явный вызов для моего сервера auth для обмена токенами.

    Вы можете увидеть примеры реализации клиента Java, но я сомневаюсь, что вы собираетесь использовать Java-клиент в производстве: https://spring.io/guides/tutorials/spring-boot-oauth2/

+0

позвольте мне подтвердить мое понимание. Вы передали уже полученный токен из FB на ваш сервер, и ваш сервер выпустил новый JWT? как вы это вызвали? Каков был URL? какие библиотеки вы использовали для достижения этого – zalis

+0

@zalis Я попытался немного прояснить ситуацию в конце. Надеюсь, это поможет. Но все же многое может быть различным, зависит от технических требований к вашему проекту – maret

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