mirror of
https://github.com/google/nomulus.git
synced 2025-06-30 08:13:32 +02:00
Add request/auth package to Nomulus release
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=147087621
This commit is contained in:
parent
c41f5bb31c
commit
dc66cef8ae
13 changed files with 808 additions and 1 deletions
|
@ -0,0 +1,125 @@
|
|||
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// 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 google.registry.request.auth;
|
||||
|
||||
import static com.google.common.net.HttpHeaders.AUTHORIZATION;
|
||||
import static google.registry.request.auth.AuthLevel.NONE;
|
||||
import static google.registry.request.auth.AuthLevel.USER;
|
||||
|
||||
import com.google.appengine.api.oauth.OAuthRequestException;
|
||||
import com.google.appengine.api.oauth.OAuthService;
|
||||
import com.google.appengine.api.oauth.OAuthServiceFailureException;
|
||||
import com.google.appengine.api.users.User;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import javax.inject.Inject;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* OAuth authentication mechanism, using the OAuthService interface.
|
||||
*
|
||||
* Only OAuth version 2 is supported.
|
||||
*/
|
||||
public class OAuthAuthenticationMechanism implements AuthenticationMechanism {
|
||||
|
||||
private static final String BEARER_PREFIX = "Bearer ";
|
||||
|
||||
private final OAuthService oauthService;
|
||||
|
||||
/** The available OAuth scopes for which {@link OAuthService} should check. */
|
||||
private final ImmutableSet<String> availableOauthScopes;
|
||||
|
||||
/** The OAuth scopes which must all be present for authentication to succeed. */
|
||||
private final ImmutableSet<String> requiredOauthScopes;
|
||||
|
||||
private final ImmutableSet<String> allowedOauthClientIds;
|
||||
|
||||
@VisibleForTesting
|
||||
@Inject
|
||||
public OAuthAuthenticationMechanism(
|
||||
OAuthService oauthService,
|
||||
@Config("availableOauthScopes") ImmutableSet<String> availableOauthScopes,
|
||||
@Config("requiredOauthScopes") ImmutableSet<String> requiredOauthScopes,
|
||||
@Config("allowedOauthClientIds") ImmutableSet<String> allowedOauthClientIds) {
|
||||
this.oauthService = oauthService;
|
||||
this.availableOauthScopes = availableOauthScopes;
|
||||
this.requiredOauthScopes = requiredOauthScopes;
|
||||
this.allowedOauthClientIds = allowedOauthClientIds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthResult authenticate(HttpServletRequest request) {
|
||||
|
||||
// Make sure that there is an Authorization header in Bearer form. OAuthService also accepts
|
||||
// tokens in the request body and URL string, but we should not use those, since they are more
|
||||
// likely to be logged than the Authorization header. Checking to make sure there's a token also
|
||||
// avoids unnecessary RPCs, since OAuthService itself does not check whether the header is
|
||||
// present. In theory, there could be more than one Authorization header, but we only check the
|
||||
// first one, because there's not a legitimate use case for having more than one, and
|
||||
// OAuthService itself only looks at the first one anyway.
|
||||
String header = request.getHeader(AUTHORIZATION);
|
||||
if ((header == null) || !header.startsWith(BEARER_PREFIX)) {
|
||||
return AuthResult.create(NONE);
|
||||
}
|
||||
// Assume that, if a bearer token is found, it's what OAuthService will use to attempt
|
||||
// authentication. This is not technically guaranteed by the contract of OAuthService; see
|
||||
// OAuthTokenInfo for more information.
|
||||
String rawAccessToken = header.substring(BEARER_PREFIX.length());
|
||||
|
||||
// Get the OAuth information. The various oauthService method calls use a single cached
|
||||
// authentication result, we can call them one by one. Unfortunately, the calls have a
|
||||
// single-scope form, and a varargs scope list form, but no way to call them with a collection
|
||||
// of scopes, so it will not be easy to configure multiple scopes.
|
||||
User currentUser;
|
||||
boolean isUserAdmin;
|
||||
String clientId;
|
||||
ImmutableSet<String> authorizedScopes;
|
||||
try {
|
||||
currentUser = oauthService.getCurrentUser(availableOauthScopes.toArray(new String[0]));
|
||||
isUserAdmin = oauthService.isUserAdmin(availableOauthScopes.toArray(new String[0]));
|
||||
clientId = oauthService.getClientId(availableOauthScopes.toArray(new String[0]));
|
||||
authorizedScopes = ImmutableSet
|
||||
.copyOf(oauthService.getAuthorizedScopes(availableOauthScopes.toArray(new String[0])));
|
||||
} catch (OAuthRequestException | OAuthServiceFailureException e) {
|
||||
return AuthResult.create(NONE);
|
||||
}
|
||||
if ((currentUser == null) || (clientId == null) || (authorizedScopes == null)) {
|
||||
return AuthResult.create(NONE);
|
||||
}
|
||||
|
||||
// Make sure that the client ID matches, to avoid a confused deputy attack; see:
|
||||
// http://stackoverflow.com/a/17439317/1179226
|
||||
if (!allowedOauthClientIds.contains(clientId)) {
|
||||
return AuthResult.create(NONE);
|
||||
}
|
||||
|
||||
// Make sure that all required scopes are present.
|
||||
if (!authorizedScopes.containsAll(requiredOauthScopes)) {
|
||||
return AuthResult.create(NONE);
|
||||
}
|
||||
|
||||
// Create the {@link AuthResult}, including the OAuth token info.
|
||||
return AuthResult.create(
|
||||
USER,
|
||||
UserAuthInfo.create(
|
||||
currentUser,
|
||||
isUserAdmin,
|
||||
OAuthTokenInfo.create(
|
||||
ImmutableSet.copyOf(authorizedScopes),
|
||||
clientId,
|
||||
rawAccessToken)));
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue