Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accept facebook login into my REST API

I have a backend server (Java / Spring / Spring Security). Currently when users from mobile app login, they simply submit their username/password and Spring Security creates a Session and assign it to the request with a JSESSIONID.

We would now also have a button on the mobile app "Login with Facebook". Here is my understanding of how it will work.

  1. mobile app uses facebook SDK to get an "access_token"
  2. mobile app retrive USer Profile from facebook (name,surname,email etc..)
  3. mobile checks (against MY server) if the username is unique
  4. If username unique, call MY REST api, with something like this /login/facebook POST over SSL and passing the access_token, email, username etc...)
  5. my server then checks if the access_token is valid

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

  6. If yes, if the UID returned by facebook is already present in my local database, I signin the user as follow:
SecurityContextHolder.getContext().setAuthentication(
                new UsernamePasswordAuthenticationToken(username, null, ROLE_USER));
  1. If i don't find the UID, I just create a new user and login the user.

  2. and from now on every request made to the server by the mobile will have the SESSION (created and attached by spring security) and the mobile app is authenticated

Could someone tell me if this is a good way of doing things ? Should I stop using sessions and switch to Spring-Security-OAUTH2 ?


EDIT 1

Based on Dave advices here is the updated spring-security config:

    <!- 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>
like image 736
Johny19 Avatar asked Jan 02 '15 16:01

Johny19


1 Answers

Facebook is already using OAuth2 server side, and provides its own native SDK for clients, so I don't see any advantage in your case of using OAuth2 in your server as well, unless your use case extends beyond what you outline above. Spring OAuth2 also has client side support, but not in a native app, so I don't really see anything at all wrong in principle with your proposal. You didn't say in any detail where you would set the security context up in your server, and I think that might be an important detail -- it has to happen in the security filter chain in the right place to get the session to be updated.

like image 183
Dave Syer Avatar answered Nov 15 '22 08:11

Dave Syer