I haven't been able to find the documentation for Spring-managed tokens, and how to cache them. The below code triggers an auth call to get the token EVERY time I call the remove service.
I'm using Spring OAuth with default configuration as follows:
#Bean(name="serviceRestTemplate")
public RestTemplate serviceRestTemplate(
#Value("${authUri}") String authUri,
#Value("${username}") String username,
#Value("${password}") String password,
#Value("${readTimeout}") int readTimeout,
#Value("${connectTimeout}") int connectTimeout) {
ClientCredentialsResourceDetails details = new ClientCredentialsResourceDetails();
details.setAccessTokenUri(authUri);
details.setClientId(username);
details.setClientSecret(password);
RestTemplate restTemplate = new OAuth2RestTemplate(details, new DefaultOAuth2ClientContext(new DefaultAccessTokenRequest());
}
My questions are:
What is the default behavior? / Is there any kind of caching with the above?
Can I enable token caching through Spring?
Related
Problem: My java springboot application receives JWT token from external system to authenticate a user with their external identity management provider which returns the user details upon success.
Once userdetails is received, the backend application must create a redirect url for the external system end user. The redirect url will land the user on my angular application to show the landing page.
Here on, all the rest api's should be allowed through an http session.
In case the user tries to access the rest api's directly, he should get an Authentication error.
How can we achieve authorization in this case since authentication was not done by my spring boot application. Can we create custom Spring session using spring security and manually put userDetails in the SecurityContext?
I am currently dealing JWT tokens obtained from Google. Including Google, pretty much all authorization servers provide rest APIs such as GET /userInfo, where you can carry the JWT token in the request header or in the URL as a GET parameter, and then verify if the JWT token is valid, non-expired, etc.
Because verifying a JWT token is usually stateless, these APIs generally come with a generous limit and you can call them as many times as you need.
I assume that you have Spring security integrated and then you can add a filter. In this way, every request has to be verified for its token in the header.
#Service
public class TokenAuthenticationFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
try {
String header = request.getHeader("Authorization");
RestTemplate restTemplate = new RestTemplate(); // If you use Google SDK, xxx SDK, you do not have to use restTemplate
String userInfoUrl = "https://example.com/api/userInfo";
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", header);
HttpEntity entity = new HttpEntity(headers);
ResponseEntity<String> response = restTemplate.exchange(
userInfoUrl, HttpMethod.GET, entity, String.class, param);
User user = response.getBody(); // Get your response and figure out if the Token is valid.
// If the token is valid? Check it here....
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
} catch (Exception ex) {
logger.error("Could not set user authentication in security context", ex);
}
filterChain.doFilter(request, response);
}
}
I have Jhipster running with Oauth2 + Keycloak.
I have a use case where I need to update user last and first name from the Jhipster React UI, so I used the Keycloak admin client via a service account to update user attributes in Keycloak.
The problem is that the information needs to be re-fetched to the OIDC token to let the user see the changes immediately. (similar issue here: https://github.com/jhipster/generator-jhipster/issues/7398 )
Is there any suggestion how to setup Spring Security to be able to re-fetch/refresh my token with the latest information form Keycloak, or any explicit call to do it?
Thanks for the answears!
So from workflow point of view I was able to solve the problem by:
Changing the data via Keycloak admin client
Change the data in the Spring Security Context
I had a wrong assumption about spring security that it validates the token data against the actual token stored in the context on every call. It turned out the spring security has no problem by changing the data in the context, so on the next login I can get a valid token what is inline with the actual data.
This is the code I was able to change the context with:
public void updateUserRole(AbstractAuthenticationToken abstractAuthenticationToken)
{
SecurityUtils.getCurrentUserLogin().flatMap(userRepository::findOneByLogin)
.ifPresent(user -> {
Set<Authority> authorities = user.getAuthorities();
Authority authority = new Authority();
authority.setName(AuthoritiesConstants.USER);
authorities.remove(AuthoritiesConstants.INVITED);
authorities.add(authority);
user.setAuthorities(authorities);
this.clearUserCaches(user);
log.debug("Changed Information for User: {}", user);
});
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
List<GrantedAuthority> authorities = List.of(new SimpleGrantedAuthority(AuthoritiesConstants.USER));
Map<String, Object> claims = ((OidcIdToken)((DefaultOidcUser)((OAuth2AuthenticationToken)abstractAuthenticationToken).getPrincipal()).getIdToken()).getClaims();
String userNameKey = ((OAuth2AuthenticationToken)authentication).getAuthorizedClientRegistrationId();
String tokenValue = ((OidcIdToken) ((DefaultOidcUser) ((OAuth2AuthenticationToken) abstractAuthenticationToken).getPrincipal()).getIdToken()).getTokenValue();
Instant issuedAt = ((OidcIdToken) ((DefaultOidcUser) ((OAuth2AuthenticationToken) abstractAuthenticationToken).getPrincipal()).getIdToken()).getIssuedAt();
Instant expiresAt = ((OidcIdToken) ((DefaultOidcUser) ((OAuth2AuthenticationToken) abstractAuthenticationToken).getPrincipal()).getIdToken()).getExpiresAt();
OidcIdToken oidcIdToken = new OidcIdToken(tokenValue, issuedAt, expiresAt, claims);
DefaultOidcUser user = new DefaultOidcUser(authorities, oidcIdToken, "name");
OAuth2AuthenticationToken oAuth2AuthenticationToken = new OAuth2AuthenticationToken(user, authorities, userNameKey);
SecurityContextHolder.getContext().setAuthentication(oAuth2AuthenticationToken);
}
I separate my application into 2 parts:
Front end : Vue js and connected with AWS congnito for login feature (email/pw or google social login).
Back end : Spring boot Restful. User information stored in database (a unique id from congnito as primary key.)
My flow of authentication
User redirected to congnito and login. congnito will return a unique id and JWT.
Front end passes the unique id and JWT to back end controller.
backend validate JWT and return user information from DB
My question is:
Is this a bad practice to authenticate on front end and pass data to back end for spring security? If so, may I have any suggestion to change my implementation flow?
To call AuthenticationProvider.authenticate, a Authentication consist username (in my case, the unique id from cognito) and password is needed (UsernamePasswordAuthenticationToken). Are there any implementation to set only username? or it is fine to set password as empty string?
// controller
public String login(HttpServletRequest req, String cognitoId, String jwt) {
// check JWT with AWS
if(!AwsJwtChecker(cognitoId, jwt))
return createErrorResponseJson("invalid jwt");
UsernamePasswordAuthenticationToken authReq
= new UsernamePasswordAuthenticationToken(cognitoId, "");
Authentication auth = authManager.authenticate(authReq);
SecurityContext sc = SecurityContextHolder.getContext();
sc.setAuthentication(auth);
HttpSession session = req.getSession(true);
session.setAttribute(SPRING_SECURITY_CONTEXT_KEY, sc);
MyUser user = userRepository.selectUserByCognitoId(cognitoId);
return createLoginSuccessResponse(user);
}
// web config
#Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
#Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String cognitoId = authentication.getName();
// check user exist in db or not
MyUser user = userRepository.selectUserByCognitoId(cognitoId);
if (user != null) {
return new UsernamePasswordAuthenticationToken(username, "", user.getRoles());
} else {
throw new BadCredentialsException("Authentication failed");
}
}
#Override
public boolean supports(Class<?>aClass) {
return aClass.equals(UsernamePasswordAuthenticationToken.class);
}
}
Is this a bad practice to authenticate on front end and pass data to back end for spring security? If so, may I have any suggestion to change my implementation flow?
No, in fact it's best practice. JWT is exactly for that purpose: You can store information about the user and because of the signature of the token, you can be certain, that the information is trustworthy.
You don't describe what you are saving in the database, but from my perspective, you are mixing two authentication methods. While it's not forbidden, it might be unnecessary. Have you analysed your token with jwt.io? There are many information about the user within the token and more can be added.
Cognito is limited in some ways, like number of groups, but for a basic application it might be enough. It has a great API to manage users from within your application, like adding groups or settings properties.
You don't describe what you do with the information that is returned with 3). Vue can too use the information stored in the jwt to display a username or something like that. You can decode the token with the jwt-decode library, eg, and get an object with all information.
To call AuthenticationProvider.authenticate...
Having said that, my answer to your second question is: You don't need the whole authentication part in you login method.
// controller
public String login(HttpServletRequest req, String cognitoId, String jwt) {
// check JWT with AWS
if(!AwsJwtChecker(cognitoId, jwt))
return createErrorResponseJson("invalid jwt");
return userRepository.selectUserByCognitoId(cognitoId);
}
This should be completely enough, since you already validate the token. No need to authenticate the user again. When spring security is set up correctly, the jwt will be set in the SecurityContext automatically.
The problem I see with your implementation is that anyone could send a valid jwt and a random cognitoId and receive user information from the database. So it would be better to parse the jwt and use something from within the jwt, like username, as identifier in the database. The token can't be manipulated, otherwise the validation fails.
public String login(String jwt) {
// check JWT with AWS
if(!AwsJwtChecker(jwt))
return createErrorResponseJson("invalid jwt");
String identifier = getIdentifier(jwt);
return userRepository.selectUserByIdentifier(identifier);
}
Spring Boot 2 with Spring Security 5 can be configured to use an openID connect ID provider for authentication.
I managed to setup up my project just by configuring Spring Security - that works fine with all kinds of perfectly preconfigured security mechanisms like mitigation of session fixation.
But it seems that Spring Security does not refresh the tokens (which are stored in the session) by itself when they are expired.
Is there a setting for that or do I have to care for the refresh myself?
Update: Spring Boot 2.1 has been released, so it is time to revisit this problem. I still have no clue if the accessToken can now be automatically refreshed or if I have to write code for doing so...
According to the documentation,
https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#webclient
When using a WebClient configured correctly, as given in the documentation it will automatically be refreshed.
Spring Security will automatically refresh expired tokens (if a refresh token is present)
This is also supported by the features matrix that refresh tokens are supported.
https://github.com/spring-projects/spring-security/wiki/OAuth-2.0-Features-Matrix
There was an older blog on Spring Security 5 that gives you access to beans that you could do this manually,
Authentication authentication =
SecurityContextHolder
.getContext()
.getAuthentication();
OAuth2AuthenticationToken oauthToken =
(OAuth2AuthenticationToken) authentication;
There will be an OAuth2AuthorizedClientService automatically configured as a bean in the Spring application context, so you’ll only need to inject it into wherever you’ll use it.
OAuth2AuthorizedClient client =
clientService.loadAuthorizedClient(
oauthToken.getAuthorizedClientRegistrationId(),
oauthToken.getName());
String refreshToken = client.getRefreshToken();
And, failing to find it right now, but I assume as part of the OAuth2AuthorizedClientExchangeFilterFunction has the calls to do a refresh.
According to https://github.com/spring-projects/spring-security/issues/6742 it seems that the token is intentionally not refreshed:
An ID Token typically comes with an expiration date. The RP MAY
rely on it to expire the RP session.
Spring does not. There are two enhancements mentioned at the end which should solve some of the refresh issues - both are still open.
As a workaround, I implemented a GenericFilterBean which checks the token and clears the authentication in the current security context. Thus a new token is needed.
#Configuration
public class RefreshTokenFilterConfig {
#Bean
GenericFilterBean refreshTokenFilter(OAuth2AuthorizedClientService clientService) {
return new GenericFilterBean() {
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null && authentication instanceof OAuth2AuthenticationToken) {
OAuth2AuthenticationToken token = (OAuth2AuthenticationToken) authentication;
OAuth2AuthorizedClient client =
clientService.loadAuthorizedClient(
token.getAuthorizedClientRegistrationId(),
token.getName());
OAuth2AccessToken accessToken = client.getAccessToken();
if (accessToken.getExpiresAt().isBefore(Instant.now())) {
SecurityContextHolder.getContext().setAuthentication(null);
}
}
filterChain.doFilter(servletRequest, servletResponse);
}
};
}
}
Additionally I had to add the filter to the security config:
#Bean
public WebSecurityConfigurerAdapter webSecurityConfigurer(GenericFilterBean refreshTokenFilter) {
return new WebSecurityConfigurerAdapter() {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(refreshTokenFilter, AnonymousAuthenticationFilter.class)
Implemented with spring-boot-starter-parent and dependencies in version 2.2.7.RELEASE:
spring-boot-starter-web
spring-boot-starter-security
spring-boot-starter-oauth2-client
I appreciate opinions about this workaround since I'm still not sure if such an overhead is really needed in Spring Boot.
even a bounty of 100 rep points did not yield an answer. So I guess there is currently no mechanism implemented to automatically refresh the access token with Spring Security.
A valid alternative seems to use the spring boot keycloak adapter which is capable of refreshing the token.
I'm working with a Spring Boot + Spring Security OAuth2 application that I believe was inspired by examples from Dave Syer. The application is configured to be an OAuth2 authorization server, with a single public client using the Resource Owner Password Credentials flow. A successful token is configured to be a JWT.
The public Angular client sends a POST request to /oauth/token with a basic auth header containing the client id and secret (this was the easiest way to get the client to authenticate, even though the secret is not private). The body of the request contains username, password, and grant type of "password".
In addition to being an authentication server, the application is a RESTful resource server for users, teams, and organizations.
I'm trying to add an additional SSO authentication flow using Spring Social. I've got Spring Social configured to authenticate through external providers via /auth/[provider]; however, following requests no longer have the SecurityContext correctly set. Possibly, Spring Security OAuth server or client is overriding the SecurityContext?
If I can get the SecurityContext correctly set after the Spring Social flow, I've got a new TokenGranter that allows a new grant type of "social" that would check the SecurityContextHolder for the pre authenticated user.
I'm interested in both a solution to my specific problem with the SecurityContext (I believe it's an issue with Spring OAuth + Social integration), or a different approach for authenticating with external providers and getting a valid JWT from our own auth server.
Thanks!
I had a similar problem on a JHipster-generated web application. Finally I decided to go with the SocialAuthenticationFilter option from Spring Social (via the SpringSocialConfigurer). After a successful social login, the server automatically generates and returns the "own" access token via redirection to the client app.
Here's my try:
#Configuration
#EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter implements EnvironmentAware {
//...
#Inject
private AuthorizationServerTokenServices authTokenServices;
#Override
public void configure(HttpSecurity http) throws Exception {
SpringSocialConfigurer socialCfg = new SpringSocialConfigurer();
socialCfg
.addObjectPostProcessor(new ObjectPostProcessor<SocialAuthenticationFilter>() {
#SuppressWarnings("unchecked")
public SocialAuthenticationFilter postProcess(SocialAuthenticationFilter filter){
filter.setAuthenticationSuccessHandler(
new SocialAuthenticationSuccessHandler(
authTokenServices,
YOUR_APP_CLIENT_ID
)
);
return filter;
}
});
http
//... lots of other configuration ...
.apply(socialCfg);
}
}
And the SocialAuthenticationSuccessHandler class:
public class SocialAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
public static final String REDIRECT_PATH_BASE = "/#/login";
public static final String FIELD_TOKEN = "access_token";
public static final String FIELD_EXPIRATION_SECS = "expires_in";
private final Logger log = LoggerFactory.getLogger(getClass());
private final AuthorizationServerTokenServices authTokenServices;
private final String localClientId;
public SocialAuthenticationSuccessHandler(AuthorizationServerTokenServices authTokenServices, String localClientId){
this.authTokenServices = authTokenServices;
this.localClientId = localClientId;
}
#Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
log.debug("Social user authenticated: " + authentication.getPrincipal() + ", generating and sending local auth");
OAuth2AccessToken oauth2Token = authTokenServices.createAccessToken(convertAuthentication(authentication)); //Automatically checks validity
String redirectUrl = new StringBuilder(REDIRECT_PATH_BASE)
.append("?").append(FIELD_TOKEN).append("=")
.append(encode(oauth2Token.getValue()))
.append("&").append(FIELD_EXPIRATION_SECS).append("=")
.append(oauth2Token.getExpiresIn())
.toString();
log.debug("Sending redirection to " + redirectUrl);
response.sendRedirect(redirectUrl);
}
private OAuth2Authentication convertAuthentication(Authentication authentication) {
OAuth2Request request = new OAuth2Request(null, localClientId, null, true, null,
null, null, null, null);
return new OAuth2Authentication(request,
//Other option: new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), "N/A", authorities)
new PreAuthenticatedAuthenticationToken(authentication.getPrincipal(), "N/A")
);
}
private String encode(String in){
String res = in;
try {
res = UriUtils.encode(in, GeneralConstants.ENCODING_UTF8);
} catch(UnsupportedEncodingException e){
log.error("ERROR: unsupported encoding: " + GeneralConstants.ENCODING_UTF8, e);
}
return res;
}
}
This way your client app will receive your web app's access token via redirection to /#/login?access_token=my_access_token&expires_in=seconds_to_expiration, as long as you set the corresponding REDIRECT_PATH_BASE in SocialAuthenticationSuccessHandler.
I hope it helps.
First, I would strongly recommend you to move away from the password grant for such a use case.
Public clients (JavaScript, installed applications) cannot keep their client secret confidential, that's why they MUST NOT be assigned one : any visitor inspecting your JavaScript code can discover the secret, and thus implement the same authentication page you have, storing your users passwords in the process.
The implicit grant has been created exactly for what you are doing.
Using a redirection-based flow has the advantage of leaving the authentication mechanism up to the authorization server, instead of having each of your applications have a piece of it : that's mostly the definition of Single Sign On (SSO).
With that said, your question is tightly related to this one I just answered : Own Spring OAuth2 server together with 3rdparty OAuth providers
To sum up the answer :
In the end, it's about how your authorization server secures the AuthorizationEndpoint : /oauth/authorize. Since your authorization server works, you already have a configuration class extending WebSecurityConfigurerAdapter that handles the security for /oauth/authorize with formLogin. That's where you need to integrate social stuff.
You simply cannot use a password grant for what you're trying to achieve, you must have your public client redirect to the authorization server. The authorization server will then redirect to the social login as its security mechanism for the /oauth/authorize endpoint.
I was starting with the good answer of above (https://stackoverflow.com/a/33963286/3351474) however with my version of Spring Security (4.2.8.RELEASE) this fails. The reason is that in org.springframework.security.access.intercept.AbstractSecurityInterceptor#authenticateIfRequired the PreAuthenticatedAuthenticationToken of the answer is not authenticated. Some GrantedAuthorities have to be passed.
In addition sharing the token in an URL parameter is not good, it should always be hidden in an HTTPs payload or header. Instead a HTML template is loaded and the token value is inserted into a ${token} placeholder field.
Here the revised version:
NOTE: The used UserDetails here is implementing org.springframework.security.core.userdetails.UserDetails
#Component
public class SocialAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
#Autowired
private OAuth2TokenStore tokenStore;
#Qualifier("tokenServices")
#Autowired
private AuthorizationServerTokenServices authTokenServices;
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
IClient user = ((SocialUserDetails) authentication.getPrincipal()).getUser();
// registration is not finished, forward the user, a marker interface
// IRegistration is used here, remove this if there no two step approach to
// create a user from a social network
if (user instanceof IRegistration) {
response.sendRedirect(subscriberRegistrationUrl + "/" + user.getId());
}
OAuth2AccessToken token = loginUser(user);
// load a HTML template from the class path and replace the token placeholder within, the HTML should contain a redirect to the actual page, but must store the token in a safe place, e.g. for preventing CSRF in the `sessionStorage` JavaScript storage.
String html = IOUtils.toString(getClass().getResourceAsStream("/html/socialLoginRedirect.html"));
html = html.replace("${token}", token.getValue());
response.getOutputStream().write(html.getBytes(StandardCharsets.UTF_8));
}
private OAuth2Authentication convertAuthentication(Authentication authentication) {
OAuth2Request request = new OAuth2Request(null, authentication.getName(),
authentication.getAuthorities(), true, null,
null, null, null, null);
// note here the passing of the authentication.getAuthorities()
return new OAuth2Authentication(request,
new PreAuthenticatedAuthenticationToken(authentication.getPrincipal(), "N/A", authentication.getAuthorities())
);
}
/**
* Logs in a user.
*/
public OAuth2AccessToken loginUser(IClient user) {
SecurityContext securityContext = SecurityContextHolder.getContext();
UserDetails userDetails = new UserDetails(user);
Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, "N/A", userDetails.getAuthorities());
securityContext.setAuthentication(authentication);
OAuth2Authentication oAuth2Authentication = convertAuthentication(authentication);
// delete the token because the client id in the DB is calculated as hash of the username and client id (here also also identical to username), this would be identical to the
// to an existing user. This existing one can come from a user registration or a previous user with the same name.
// If a new entity with a different ID is used the stored token hash would differ and the the wrong token would be retrieved
tokenStore.deleteTokensForUserId(user.getUsername());
OAuth2AccessToken oAuth2AccessToken = authTokenServices.createAccessToken(oAuth2Authentication);
// the DB id of the created user is returned as additional data, can be
// removed if not needed
((DefaultOAuth2AccessToken) oAuth2AccessToken).setAdditionalInformation(new HashMap<>());
oAuth2AccessToken.getAdditionalInformation().put("userId", user.getId());
return oAuth2AccessToken;
}
}
Example socialLoginRedirect.html:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Example App</title>
<meta http-equiv="Refresh" content="0; url=/index.html#/home"/>
</head>
<script>
window.sessionStorage.setItem('access_token', '${token}');
</script>
<body>
<p>Please follow this link.</p>
</body>
</html>
The configuration wiring in a WebSecurityConfigurerAdapter:
#Configuration
#EnableWebSecurity
#EnableWebMvc
#Import(WebServiceConfig.class)
public class AuthenticationConfig extends WebSecurityConfigurerAdapter {
#Value("${registrationUrl}")
private String registrationUrl;
#Autowired
private SocialAuthenticationSuccessHandler socialAuthenticationSuccessHandler;
#Value("${loginUrl}")
private String loginUrl;
#Override
protected void configure(HttpSecurity http) throws Exception {
List<String> permitAllUrls = new ArrayList<>();
// permit social log in
permitAllUrls.add("/auth/**");
http.authorizeRequests().antMatchers(permitAllUrls.toArray(new String[0])).permitAll();
SpringSocialConfigurer springSocialConfigurer = new SpringSocialConfigurer();
springSocialConfigurer.signupUrl(registrationUrl);
springSocialConfigurer.postFailureUrl(loginUrl);
springSocialConfigurer
.addObjectPostProcessor(new ObjectPostProcessor<SocialAuthenticationFilter>() {
#SuppressWarnings("unchecked")
public SocialAuthenticationFilter postProcess(SocialAuthenticationFilter filter){
filter.setAuthenticationSuccessHandler(socialAuthenticationSuccessHandler);
return filter;
}
});
http.apply(springSocialConfigurer);
http.logout().disable().csrf().disable();
http.requiresChannel().anyRequest().requiresSecure();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
I implemented spring oauth2 to secure my rest services and additionally add social login and implicit signup for first time login . for user user you can generate the token using username and password only problem with generate the token for social user . for that you have to implement the Filter that will intercept your /oauth/token request before processing . here if you want to generate the the token for social user pass the username and facebook token , here you can use facebook token as password and generate the token for facebook user also . if facebook token updated then you have to write a db trigger also to update you token in user table .... may be it will help you