Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add method to revoke a refresh_token #86

Merged
merged 2 commits into from
Apr 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ public class AuthenticationAPIClient {
private static final String PASSWORD_KEY = "password";
private static final String EMAIL_KEY = "email";
private static final String PHONE_NUMBER_KEY = "phone_number";
private static final String OAUTH_CODE_KEY = "code";
private static final String REDIRECT_URI_KEY = "redirect_uri";
private static final String TOKEN_KEY = "token";
private static final String DELEGATION_PATH = "delegation";
private static final String ACCESS_TOKEN_PATH = "access_token";
private static final String SIGN_UP_PATH = "signup";
Expand All @@ -90,8 +93,7 @@ public class AuthenticationAPIClient {
private static final String RESOURCE_OWNER_PATH = "ro";
private static final String TOKEN_INFO_PATH = "tokeninfo";
private static final String USER_INFO_PATH = "userinfo";
private static final String OAUTH_CODE_KEY = "code";
private static final String REDIRECT_URI_KEY = "redirect_uri";
private static final String REVOKE_PATH = "revoke";
private static final String HEADER_AUTHORIZATION = "Authorization";

private final Auth0 auth0;
Expand Down Expand Up @@ -617,6 +619,43 @@ public DatabaseConnectionRequest<Void, AuthenticationException> resetPassword(@N
return new DatabaseConnectionRequest<>(request);
}

/**
* Request the revoke of a given refresh_token. Once revoked, the refresh_token cannot be used to obtain new tokens.
* The client must be of type 'Native' or have the 'Token Endpoint Authentication Method' set to 'none' for this endpoint to work.
*
* Example usage:
* <pre>
* {@code
* client.revokeToken("{refresh_token}")
* .start(new BaseCallback<Void>() {
* {@literal}Override
* public void onSuccess(Void payload) {}
*
* {@literal}Override
* public void onFailure(AuthenticationException error) {}
* });
* }
* </pre>
*
* @param refreshToken the token to revoke
* @return a request to start
*/
@SuppressWarnings("WeakerAccess")
public Request<Void, AuthenticationException> revokeToken(@NonNull String refreshToken) {
final Map<String, Object> parameters = ParameterBuilder.newBuilder()
.setClientId(getClientId())
.set(TOKEN_KEY, refreshToken)
.asDictionary();

HttpUrl url = HttpUrl.parse(auth0.getDomainUrl()).newBuilder()
.addPathSegment(OAUTH_PATH)
.addPathSegment(REVOKE_PATH)
.build();

return factory.POST(url, client, gson, authErrorBuilder)
.addParameters(parameters);
}

/**
* Requests new Credentials using a valid Refresh Token. The received token will have the same audience and scope as first requested. How the new Credentials are requested depends on the {@link Auth0#isOIDCConformant()} flag.
* - If the instance is OIDC Conformant the endpoint will be /oauth/token with 'refresh_token' grant, and the response will include an id_token and an access_token if 'openid' scope was requested when the refresh_token was obtained.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1573,6 +1573,46 @@ public void shouldFetchProfileAfterLoginRequest() throws Exception {
assertThat(callback, hasPayloadOfType(Authentication.class));
}


@Test
public void shouldRevokeToken() throws Exception {
Auth0 auth0 = new Auth0(CLIENT_ID, mockAPI.getDomain(), mockAPI.getDomain());
AuthenticationAPIClient client = new AuthenticationAPIClient(auth0);

mockAPI.willReturnSuccessfulEmptyBody();
final MockAuthenticationCallback<Void> callback = new MockAuthenticationCallback<>();
client.revokeToken("refreshToken")
.start(callback);

final RecordedRequest request = mockAPI.takeRequest();
assertThat(request.getHeader("Accept-Language"), is(getDefaultLocale()));
assertThat(request.getPath(), equalTo("/oauth/revoke"));

Map<String, String> body = bodyFromRequest(request);
assertThat(body, hasEntry("client_id", CLIENT_ID));
assertThat(body, hasEntry("token", "refreshToken"));

assertThat(callback, hasNoError());
}

@Test
public void shouldRevokeTokenSync() throws Exception {
Auth0 auth0 = new Auth0(CLIENT_ID, mockAPI.getDomain(), mockAPI.getDomain());
AuthenticationAPIClient client = new AuthenticationAPIClient(auth0);

mockAPI.willReturnSuccessfulEmptyBody();
client.revokeToken("refreshToken")
.execute();

final RecordedRequest request = mockAPI.takeRequest();
assertThat(request.getHeader("Accept-Language"), is(getDefaultLocale()));
assertThat(request.getPath(), equalTo("/oauth/revoke"));

Map<String, String> body = bodyFromRequest(request);
assertThat(body, hasEntry("client_id", CLIENT_ID));
assertThat(body, hasEntry("token", "refreshToken"));
}

@Test
public void shouldRenewAuthWithOAuthTokenIfOIDCConformant() throws Exception {
Auth0 auth0 = new Auth0(CLIENT_ID, mockAPI.getDomain(), mockAPI.getDomain());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ public AuthenticationAPI willReturnSuccessfulSignUp() {
return this;
}

public AuthenticationAPI willReturnSuccessfulEmptyBody() {
server.enqueue(responseEmpty(200));
return this;
}

public AuthenticationAPI willReturnSuccessfulLogin() {
String json = "{\n" +
" \"refresh_token\": \"" + REFRESH_TOKEN + "\",\n" +
Expand Down Expand Up @@ -175,7 +180,12 @@ public AuthenticationAPI willReturnApplicationResponseWithBody(String body, int
return this;
}

private MockResponse responseWithPlainText(String statusMessage, int statusCode){
private MockResponse responseEmpty(int statusCode) {
return new MockResponse()
.setResponseCode(statusCode);
}

private MockResponse responseWithPlainText(String statusMessage, int statusCode) {
return new MockResponse()
.setResponseCode(statusCode)
.addHeader("Content-Type", "text/plain")
Expand Down