Search in sources :

Example 1 with AccessToken

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);
}
Also used : AccessToken(io.cdap.cdap.security.auth.AccessToken) UserIdentity(io.cdap.cdap.security.auth.UserIdentity) JsonObject(com.google.gson.JsonObject)

Example 2 with AccessToken

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();
    }
}
Also used : HttpURLConnection(java.net.HttpURLConnection) InputStream(java.io.InputStream) AccessToken(io.cdap.cdap.security.auth.AccessToken) JsonObject(com.google.gson.JsonObject) ByteArrayOutputStream(java.io.ByteArrayOutputStream) JsonParser(com.google.gson.JsonParser) Test(org.junit.Test)

Example 3 with AccessToken

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);
    }
}
Also used : Credential(io.cdap.cdap.proto.security.Credential) AccessToken(io.cdap.cdap.security.auth.AccessToken) UserIdentity(io.cdap.cdap.security.auth.UserIdentity) IOException(java.io.IOException) Principal(io.cdap.cdap.proto.security.Principal)

Example 4 with AccessToken

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));
    }
}
Also used : InvalidTokenException(io.cdap.cdap.security.auth.InvalidTokenException) AccessException(io.cdap.cdap.api.security.AccessException) AccessToken(io.cdap.cdap.security.auth.AccessToken) UserIdentity(io.cdap.cdap.security.auth.UserIdentity) IOException(java.io.IOException)

Example 5 with AccessToken

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();
    }
}
Also used : HttpURLConnection(java.net.HttpURLConnection) InputStream(java.io.InputStream) AccessToken(io.cdap.cdap.security.auth.AccessToken) JsonObject(com.google.gson.JsonObject) ByteArrayOutputStream(java.io.ByteArrayOutputStream) JsonParser(com.google.gson.JsonParser) Test(org.junit.Test)

Aggregations

AccessToken (io.cdap.cdap.security.auth.AccessToken)6 UserIdentity (io.cdap.cdap.security.auth.UserIdentity)4 JsonObject (com.google.gson.JsonObject)3 IOException (java.io.IOException)3 JsonParser (com.google.gson.JsonParser)2 ByteArrayOutputStream (java.io.ByteArrayOutputStream)2 InputStream (java.io.InputStream)2 HttpURLConnection (java.net.HttpURLConnection)2 Test (org.junit.Test)2 AccessException (io.cdap.cdap.api.security.AccessException)1 Credential (io.cdap.cdap.proto.security.Credential)1 Principal (io.cdap.cdap.proto.security.Principal)1 InvalidTokenException (io.cdap.cdap.security.auth.InvalidTokenException)1 OutputStream (java.io.OutputStream)1 Location (org.apache.twill.filesystem.Location)1