use of io.cdap.cdap.security.auth.AccessToken in project cdap by caskdata.
the class GrantAccessToken method grantToken.
private void grantToken(HttpServletRequest request, HttpServletResponse response, long tokenValidity) throws IOException, ServletException {
String username = request.getUserPrincipal().getName();
List<String> userGroups = Collections.emptyList();
long issueTime = System.currentTimeMillis();
long expireTime = issueTime + tokenValidity;
// Create and sign a new AccessTokenIdentifier to generate the AccessToken.
UserIdentity tokenIdentifier = new UserIdentity(username, UserIdentity.IdentifierType.EXTERNAL, userGroups, issueTime, expireTime);
AccessToken token = tokenManager.signIdentifier(tokenIdentifier);
LOG.debug("Issued token for user {}", username);
// Set response headers
response.setContentType("application/json;charset=UTF-8");
response.addHeader(HttpHeaderNames.CACHE_CONTROL.toString(), "no-store");
response.addHeader(HttpHeaderNames.PRAGMA.toString(), "no-cache");
// Set response body
JsonObject json = new JsonObject();
byte[] encodedIdentifier = Base64.getEncoder().encode(tokenCodec.encode(token));
json.addProperty(ExternalAuthenticationServer.ResponseFields.ACCESS_TOKEN, new String(encodedIdentifier, Charsets.UTF_8));
json.addProperty(ExternalAuthenticationServer.ResponseFields.TOKEN_TYPE, ExternalAuthenticationServer.ResponseFields.TOKEN_TYPE_BODY);
json.addProperty(ExternalAuthenticationServer.ResponseFields.EXPIRES_IN, TimeUnit.SECONDS.convert(tokenValidity, TimeUnit.MILLISECONDS));
response.getOutputStream().print(json.toString());
response.setStatus(HttpServletResponse.SC_OK);
}
use of io.cdap.cdap.security.auth.AccessToken in project cdap by caskdata.
the class ExternalAuthenticationServerTestBase method testExtendedToken.
/**
* Test getting a long lasting Access Token.
*
* @throws Exception
*/
@Test
public void testExtendedToken() throws Exception {
HttpURLConnection urlConn = openConnection(getURL(GrantAccessToken.Paths.GET_EXTENDED_TOKEN));
try {
Optional.ofNullable(getAuthRequestHeader()).ifPresent(m -> m.forEach(urlConn::addRequestProperty));
Assert.assertEquals(200, urlConn.getResponseCode());
// Test correct response body
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try (InputStream is = urlConn.getInputStream()) {
ByteStreams.copy(is, bos);
}
String responseBody = bos.toString("UTF-8");
JsonParser parser = new JsonParser();
JsonObject responseJson = (JsonObject) parser.parse(responseBody);
long expiration = responseJson.get(ExternalAuthenticationServer.ResponseFields.EXPIRES_IN).getAsLong();
long expectedExpiration = configuration.getInt(Constants.Security.EXTENDED_TOKEN_EXPIRATION);
// Test expiration time in seconds
Assert.assertEquals(expectedExpiration / 1000, expiration);
// Test that the server passes back an AccessToken object which can be decoded correctly.
String encodedToken = responseJson.get(ExternalAuthenticationServer.ResponseFields.ACCESS_TOKEN).getAsString();
AccessToken token = tokenCodec.decode(Base64.getDecoder().decode(encodedToken));
Assert.assertEquals(getAuthenticatedUserName(), token.getIdentifier().getUsername());
LOG.info("AccessToken got from ExternalAuthenticationServer is: " + encodedToken);
} finally {
urlConn.disconnect();
}
}
use of io.cdap.cdap.security.auth.AccessToken in project cdap by caskdata.
the class SystemAuthenticationContext method getPrincipal.
@Override
public Principal getPrincipal() {
// Normally userID and userCredentials should be either null or non-null.
// For non-null, they are either user or internal user credentials, so propagated as is.
// For null, it means system originated requests, user and generate a credential as internal user.
//
// It is possible that userID is non-null while userCredential is null, this can happen when we want
// to launch programs as a userID that is stored in program options' system args. As user credential
// is currently not stored there, we cannot launch program as the targeted user, instead we run program
// using system internal identity. We rely on authorization being performed at http handler level upon
// receiving request.
String userId = SecurityRequestContext.getUserId();
Credential userCredential = SecurityRequestContext.getUserCredential();
if (userId != null && userCredential != null) {
return new Principal(userId, Principal.PrincipalType.USER, userCredential);
} else if (userId != null && userCredential == null) {
LOG.warn("Unexpected SecurityRequestContext state, userId = {} while userCredential = NULL", userId);
} else if (userId == null && userCredential != null) {
LOG.warn("Unexpected SecurityRequestContext state, userId = NULL while userCredential = {}", userCredential);
}
try {
userId = UserGroupInformation.getCurrentUser().getShortUserName();
} catch (IOException e) {
throw Throwables.propagate(e);
}
long currentTimestamp = System.currentTimeMillis();
UserIdentity identity = new UserIdentity(userId, UserIdentity.IdentifierType.INTERNAL, Collections.emptyList(), currentTimestamp, currentTimestamp + DEFAULT_EXPIRATION);
AccessToken accessToken = tokenManager.signIdentifier(identity);
String encodedAccessToken;
try {
encodedAccessToken = Base64.getEncoder().encodeToString(accessTokenCodec.encode(accessToken));
Credential credential = new Credential(encodedAccessToken, Credential.CredentialType.INTERNAL);
return new Principal(userId, Principal.PrincipalType.USER, credential);
} catch (IOException e) {
throw new RuntimeException("Unexpected failure while creating internal system identity", e);
}
}
use of io.cdap.cdap.security.auth.AccessToken in project cdap by caskdata.
the class InternalAccessEnforcer method validateAccessTokenAndIdentity.
private void validateAccessTokenAndIdentity(String principalName, Credential credential) throws AccessException {
if (credential == null) {
throw new IllegalStateException("Attempted to internally enforce access on null credential");
}
if (!credential.getType().equals(Credential.CredentialType.INTERNAL)) {
throw new IllegalStateException("Attempted to internally enforce access on non-internal credential type");
}
AccessToken accessToken;
try {
accessToken = accessTokenCodec.decode(Base64.getDecoder().decode(credential.getValue()));
} catch (IOException e) {
throw new AccessException("Failed to deserialize access token", e);
}
try {
tokenManager.validateSecret(accessToken);
} catch (InvalidTokenException e) {
throw new AccessException("Failed to validate access token", e);
}
UserIdentity userIdentity = accessToken.getIdentifier();
if (!userIdentity.getUsername().equals(principalName)) {
LOG.debug(String.format("Internal access token username differs from principal name; got token " + "name '%s', expected principal name '%s'", userIdentity.getUsername(), principalName));
}
if (userIdentity.getIdentifierType() == null || !userIdentity.getIdentifierType().equals(UserIdentity.IdentifierType.INTERNAL)) {
throw new AccessException(String.format("Invalid internal access token type; got '%s', want '%s'", userIdentity.getIdentifierType(), UserIdentity.IdentifierType.INTERNAL));
}
}
use of io.cdap.cdap.security.auth.AccessToken in project cdap by caskdata.
the class ExternalAuthenticationServerTestBase method testValidAuthentication.
/**
* Test an authorized request to server.
*
* @throws Exception
*/
@Test
public void testValidAuthentication() throws Exception {
HttpURLConnection urlConn = openConnection(getURL(GrantAccessToken.Paths.GET_TOKEN));
try {
Optional.ofNullable(getAuthRequestHeader()).ifPresent(m -> m.forEach(urlConn::addRequestProperty));
Assert.assertEquals(200, urlConn.getResponseCode());
verify(TEST_AUDIT_LOGGER, timeout(10000).atLeastOnce()).trace(contains(getAuthenticatedUserName()));
// Test correct headers being returned
String cacheControlHeader = urlConn.getHeaderField(HttpHeaderNames.CACHE_CONTROL.toString());
String pragmaHeader = urlConn.getHeaderField(HttpHeaderNames.PRAGMA.toString());
String contentType = urlConn.getHeaderField(HttpHeaderNames.CONTENT_TYPE.toString());
Assert.assertEquals("no-store", cacheControlHeader);
Assert.assertEquals("no-cache", pragmaHeader);
Assert.assertEquals("application/json;charset=UTF-8", contentType);
// Test correct response body
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try (InputStream is = urlConn.getInputStream()) {
ByteStreams.copy(is, bos);
}
String responseBody = bos.toString("UTF-8");
JsonParser parser = new JsonParser();
JsonObject responseJson = (JsonObject) parser.parse(responseBody);
String tokenType = responseJson.get(ExternalAuthenticationServer.ResponseFields.TOKEN_TYPE).toString();
long expiration = responseJson.get(ExternalAuthenticationServer.ResponseFields.EXPIRES_IN).getAsLong();
Assert.assertEquals(String.format("\"%s\"", ExternalAuthenticationServer.ResponseFields.TOKEN_TYPE_BODY), tokenType);
long expectedExpiration = configuration.getInt(Constants.Security.TOKEN_EXPIRATION);
// Test expiration time in seconds
Assert.assertEquals(expectedExpiration / 1000, expiration);
// Test that the server passes back an AccessToken object which can be decoded correctly.
String encodedToken = responseJson.get(ExternalAuthenticationServer.ResponseFields.ACCESS_TOKEN).getAsString();
AccessToken token = tokenCodec.decode(Base64.getDecoder().decode(encodedToken));
Assert.assertEquals(getAuthenticatedUserName(), token.getIdentifier().getUsername());
LOG.info("AccessToken got from ExternalAuthenticationServer is: " + encodedToken);
} finally {
urlConn.disconnect();
}
}
Aggregations