Skip to content

Commit

Permalink
Implement OAuth 2.0 refresh access token
Browse files Browse the repository at this point in the history
Some OAuth providers ask to extend the access token expiration date, in
order to continue using it.
Microsoft Live do that, and it will be also soon mandatory for Facebook
because they will deprecate the 'offline_access' permission.

To refresh an access token, you need to access the accessTokenEndPoint
with other parameters like a specific 'grant_type' parameter.
  • Loading branch information
tbruyelle committed Apr 24, 2012
1 parent 1208fd8 commit b228788
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/main/java/org/scribe/builder/api/DefaultApi20.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,11 @@ public OAuthService createService(OAuthConfig config)
return new OAuth20ServiceImpl(this, config);
}

/**
* @return the parameter needed to refresh a access token.
*/
public String getRefreshTokenParameterName()
{
throw new UnsupportedOperationException("Refresh token is not implemented for "+getClass().getSimpleName());
}
}
6 changes: 6 additions & 0 deletions src/main/java/org/scribe/builder/api/FacebookApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,10 @@ public String getAuthorizationUrl(OAuthConfig config)
return String.format(AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getCallback()));
}
}

@Override
public String getRefreshTokenParameterName()
{
return "fb_exchange_token";
}
}
6 changes: 6 additions & 0 deletions src/main/java/org/scribe/builder/api/LiveApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,10 @@ public AccessTokenExtractor getAccessTokenExtractor()
{
return new JsonTokenExtractor();
}

@Override
public String getRefreshTokenParameterName()
{
return "refresh_token";
}
}
1 change: 1 addition & 0 deletions src/main/java/org/scribe/model/OAuthConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,6 @@ public class OAuthConstants
public static final String CLIENT_SECRET = "client_secret";
public static final String REDIRECT_URI = "redirect_uri";
public static final String CODE = "code";
public static final String GRANT_TYPE = "grant_type";

}
8 changes: 8 additions & 0 deletions src/main/java/org/scribe/oauth/OAuth10aServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,14 @@ public Token getAccessToken(Token requestToken, Verifier verifier)
return api.getAccessTokenExtractor().extract(response.getBody());
}

/**
* {@inheritDoc}
*/
public Token refreshAccessToken(Token accessToken)
{
throw new UnsupportedOperationException("Refresh token is not supported in Scribe OAuth 1.0");
}

/**
* {@inheritDoc}
*/
Expand Down
22 changes: 22 additions & 0 deletions src/main/java/org/scribe/oauth/OAuth20ServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,28 @@ public Token getAccessToken(Token requestToken, Verifier verifier)
return api.getAccessTokenExtractor().extract(response.getBody());
}

/**
* {@inheritDoc}
*/
public Token refreshAccessToken(Token accessToken)
{

String accessTokenEndpoint = api.getAccessTokenEndpoint();
if (accessTokenEndpoint.contains("?grant_type="))
{
// handle the ugly case where the grant_type parameter is already hardcoded in the constant url
accessTokenEndpoint = accessTokenEndpoint.substring(0, accessTokenEndpoint.indexOf("?"));
}
OAuthRequest request = new OAuthRequest(api.getAccessTokenVerb(), accessTokenEndpoint);
request.addQuerystringParameter(OAuthConstants.CLIENT_ID, config.getApiKey());
request.addQuerystringParameter(OAuthConstants.CLIENT_SECRET, config.getApiSecret());
request.addQuerystringParameter(OAuthConstants.REDIRECT_URI, config.getCallback());
request.addQuerystringParameter(OAuthConstants.GRANT_TYPE, api.getRefreshTokenParameterName());
request.addQuerystringParameter(api.getRefreshTokenParameterName(), accessToken.getToken());
Response response = request.send();
return api.getAccessTokenExtractor().extract(response.getBody());
}

/**
* {@inheritDoc}
*/
Expand Down
13 changes: 13 additions & 0 deletions src/main/java/org/scribe/oauth/OAuthService.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,19 @@ public interface OAuthService
*/
public Token getAccessToken(Token requestToken, Verifier verifier);

/**
* Refresh the access token to extend its expiration date.
* <p/>
* For the token in parameter, Facebook needs the access_token, while Live
* needs the refresh_token (which can be found only in the
* {@link org.scribe.model.Token#getRawResponse()} returned by
* {@link #getAccessToken(org.scribe.model.Token, org.scribe.model.Verifier)})
*
* @param accessToken access or refresh token, depending on the OAuth provider
* @return fresh access token
*/
public Token refreshAccessToken(Token accessToken);

/**
* Signs am OAuth request
*
Expand Down

0 comments on commit b228788

Please sign in to comment.