Принять вход в facebook в мой REST API

У меня есть внутренний сервер (Java/Spring/Spring Security). В настоящее время, когда пользователи из мобильного приложения входят в систему, они просто отправляют свое имя пользователя/пароль, а Spring Security создает сеанс и назначает его запросу с JSESSIONID.

Теперь у нас также будет кнопка в мобильном приложении «Войти через Facebook». Вот как я понимаю, как это будет работать.

  1. мобильное приложение использует facebook SDK для получения «access_token»
  2. мобильное приложение извлекает профиль пользователя из facebook (имя, фамилия, адрес электронной почты и т. д.)
  3. мобильные проверки (против МОЕГО сервера), если имя пользователя уникально
  4. Если имя пользователя уникально, вызовите MY REST api с помощью чего-то вроде этого /login/facebook POST через SSL и передачи access_token, электронной почты, имени пользователя и т. д.)
  5. затем мой сервер проверяет, действителен ли access_token

    GET graph.facebook.com/debug_token? input_token={token-to-inspect} &access_token={app-token-or-admin-token}

  6. Если да, если UID, возвращенный facebook, уже присутствует в моей локальной базе данных, я вхожу в систему следующим образом:
SecurityContextHolder.getContext().setAuthentication(
                new UsernamePasswordAuthenticationToken(username, null, ROLE_USER));
  1. Если я не нахожу UID, я просто создаю нового пользователя и вхожу в него.

  2. и с этого момента каждый запрос, сделанный на сервер мобильным устройством, будет иметь SESSION (созданную и прикрепленную Spring Security), и мобильное приложение будет аутентифицировано

Может кто-нибудь сказать мне, если это хороший способ сделать что-то? Должен ли я прекратить использование сеансов и переключиться на Spring-Security-OAUTH2?


ИЗМЕНИТЬ 1

Основываясь на советах Дэйва, вот обновленная конфигурация spring-security:

    <!- handle login by providing a token-->
    <security:http pattern="/login/facebook" auto-config="false" use-expressions="true" entry-point-ref="loginUrlAuthenticationEntryPoint">
                <security:custom-filter ref="facebookLoginFilter" position="FORM_LOGIN_FILTER"/>
                <security:intercept-url pattern="/**" access="isAuthenticated()" />
    </security:http>


    <bean id="loginUrlAuthenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
                <constructor-arg value="/login/facebook"></constructor-arg>
    </bean>

    <!-- handle basic username + password logins-->
    <security:http auto-config="true" use-expressions="true" entry-point-ref="forbiddenEntryPoint">
                <security:form-login login-processing-url="/security_check" authentication-failure-handler-ref="authFailureHandler"
                                     default-target-url="/" always-use-default-target="true" authentication-success-handler-ref="authSuccessHandler" />
                ...
                my others patterns..
                ...

        </security:http>
<bean id="forbiddenEntryPoint"
                class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint" />

            <bean id="authSuccessHandler" class="my.package.AuthenticationSuccessHandlerImpl"/>
            <bean id="authFailureHandler" class="my.package.AuthenticationFailureHandlerImpl"/>

            <bean id="facebookLoginFilter" class="pl.jcommerce.ocean.web.ws.controller.FacebookLoginFilter">
                <property name="requiresAuthenticationRequestMatcher" ref="loginRequestUrlHandler"></property>
                <property name="authenticationManager" ref="authManager"></property>
            </bean>

            <security:authentication-manager id="authManager">
                <security:authentication-provider ref="facebookAuthenticationProvider" />
            </security:authentication-manager>

            <security:authentication-manager>
                <security:authentication-provider ref="webServiceUserAuthenticationProvider" />
            </security:authentication-manager>

            <bean id="loginRequestUrlHandler" class="org.springframework.security.web.util.matcher.RegexRequestMatcher">
                <constructor-arg index="0" value="/login/facebook" />
                <constructor-arg index="1" value="POST" />
                <constructor-arg index="2" value="false" />
            </bean>

person Johny19    schedule 02.01.2015    source источник
comment
Для этой цели реализован Spring Filter. См. следующую ссылку: Spring Authentication Filter для конечных точек REST без сохранения состояния, которые используют токен Facebook для аутентификации   -  person Ozgen    schedule 10.03.2016


Ответы (2)


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

person Dave Syer    schedule 03.01.2015
comment
Спасибо за ответ! Я думал, что с помощью Oauth2 будет проще интегрировать логин facebook. Просто идея, где у меня была бы возможность перейти с сеанса на токен. Что касается того, где я буду аутентифицировать пользователя, я действительно не знал, куда его поместить. Не могли бы вы указать мне более подробно, где он должен находиться в фильтрах? - person Johny19; 04.01.2015
comment
На вашем месте я бы посмотрел на реализацию UsernamePasswordAuthenticationFilter и адаптировал ее для работы с разными учетными данными (токен fb вместо имени пользователя/пароля). Затем вы можете добавить фильтр, используя addFilterAfter в той же позиции, что и UsernamePasswordAuthenticationFilter. - person Dave Syer; 04.01.2015
comment
отлично спасибо! Вот что я сделал: создал класс, расширяющий UsernamePasswordAuthenticationFilter, и переопределил метод tryAuthentication. Я делаю некоторую базовую проверку и создаю объект аутентификации с токеном в качестве принципала. Затем я создал этот bean-компонент в своей конфигурации и передал его в новый authenticationProvider (который будет обрабатывать проверку токена, связавшись с инструментами графа facebook, если все пойдет хорошо, я аутентифицирую пользователя). и, наконец, я создал новый ‹security:http в своей конфигурации с пользовательской точкой входа (/login/facebook). Вы одобряете? - person Johny19; 04.01.2015
comment
Звучит хорошо (кроме бита XML, но это ваши похороны). - person Dave Syer; 04.01.2015
comment
Для этой цели реализован Spring Filter. См. следующую ссылку: Spring Authentication Filter для конечных точек REST без сохранения состояния, которые используют токен Facebook для аутентификации - person Ozgen; 10.03.2016

Я попробовал реализовать что-то подобное на основе ответа Дэйва Сайера здесь вместе с материалами Spring Security Angular, которые он собрал. Чтобы увидеть пример, см. мой разветвленный репозиторий github, в частности, классы в security.

person Alex    schedule 08.04.2015