/* * Copyright (C) 2011 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.google.api.explorer.client; import com.google.api.explorer.client.base.ApiService; import com.google.api.explorer.client.base.Config; import com.google.api.gwt.oauth2.client.Auth; import com.google.api.gwt.oauth2.client.AuthRequest; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; import com.google.gwt.core.client.Callback; import java.util.Map; import java.util.Set; import javax.annotation.concurrent.Immutable; /** * Manages authentication state by accepting auth requests asynchronously and notifies callers when * auth is ready. * * @author jasonhall@google.com (Jason Hall) */ public class AuthManager { /** * Class which binds scope information with the granted auth token for more intelligent messaging * when there is insufficient auth. * */ @Immutable public class AuthToken { private final String authToken; private final ImmutableSet<String> scopes; private AuthToken(String authToken, Set<String> scopes) { this.authToken = Preconditions.checkNotNull(authToken); this.scopes = ImmutableSet.copyOf(scopes); } /** * Returns the auth token. */ public String getAuthToken() { return authToken; } /** * Returns the scopes that were used when this token was granted. */ public ImmutableSet<String> getScopes() { return scopes; } } /** * Interface which defines the callback definition format that must be implemented to receive * information about when auth has been completed. * */ public interface AuthCompleteCallback { /** * Callback method that is invoked when auth has completed successfully. * * @param token Token which was obtained. */ public void complete(AuthToken token); } private static final Map<ApiService, AuthToken> authTokens = Maps.newHashMap(); /** * Get the token stored for the current service, or {@code null} if there is * no token. */ public AuthToken getToken(ApiService service) { return authTokens.get(service); } /** * Request auth for the given service and scopes, and notify the callback when complete. * * @param service Service for which auth is being requested. * @param scopes Scopes which the user is requesting access to. * @param callback Receiver which should be notified when there is a failure. * @throws RuntimeException when an exception occurs completing the auth. */ public void requestAuth( final ApiService service, final Set<String> scopes, final AuthCompleteCallback callback) { // TODO(jasonhall): Show some indication that auth is in progress here. String[] scopeArray = scopes.toArray(new String[] {}); AuthRequest req = new AuthRequest(Config.AUTH_URL, Config.CLIENT_ID).withScopes(scopeArray); Auth.get().login(req, new Callback<String, Throwable>() { @Override public void onSuccess(String tokenString) { AuthToken token = new AuthToken(tokenString, scopes); authTokens.put(service, token); callback.complete(token); } @Override public void onFailure(Throwable caught) { // When this occurs the UI is left unchanged and the user is allowed to retry the auth // request by clicking the toggle again. throw new RuntimeException(caught); } }); } /** * "Revokes" the access token, in the sense that it tells the app to forget * that it knows the auth token. * * <p> * This method does *not* actually revoke the token on the server, but will, * when this is supported. * </p> */ public void revokeAccess(ApiService service) { // TODO(jasonhall): This should actually revoke access on the server, and // remove the token from the cookie. It currently does nothing more than // "forget" it knows the token. authTokens.remove(service); } }