Search in sources :

Example 1 with IdTokenRequest

use of com.yahoo.athenz.zts.token.IdTokenRequest in project athenz by yahoo.

the class ZTSImpl method getOIDCResponse.

@Override
public Response getOIDCResponse(ResourceContext ctx, String responseType, String clientId, String redirectUri, String scope, String state, String nonce, String keyType) {
    final String caller = ctx.getApiName();
    final String principalDomain = logPrincipalAndGetDomain(ctx);
    validateRequest(ctx.request(), principalDomain, caller);
    validate(nonce, TYPE_ENTITY_NAME, principalDomain, caller);
    validate(clientId, TYPE_SERVICE_NAME, principalDomain, caller);
    if (!StringUtil.isEmpty(state)) {
        validate(state, TYPE_ENTITY_NAME, principalDomain, caller);
    }
    if (!StringUtil.isEmpty(keyType)) {
        validate(keyType, TYPE_SIMPLE_NAME, principalDomain, caller);
    }
    clientId = clientId.toLowerCase();
    // get our principal's name
    final Principal principal = ((RsrcCtxWrapper) ctx).principal();
    String principalName = principal.getFullName();
    // verify we have a valid client id
    final String domainName = AthenzUtils.extractPrincipalDomainName(clientId);
    if (domainName == null) {
        throw requestError("Invalid client id", caller, principal.getDomain(), principalDomain);
    }
    setRequestDomain(ctx, domainName);
    // first retrieve our domain data object from the cache
    DataCache data = dataStore.getDataCache(domainName);
    if (data == null) {
        setRequestDomain(ctx, ZTSConsts.ZTS_UNKNOWN_DOMAIN);
        throw notFoundError("No such domain: " + domainName, caller, ZTSConsts.ZTS_UNKNOWN_DOMAIN, principalDomain);
    }
    final String serviceEndpoint = extractServiceEndpoint(data.getDomainData(), clientId);
    if (StringUtil.isEmpty(serviceEndpoint)) {
        throw requestError("Invalid Service or empty service endpoint", caller, principal.getDomain(), principalDomain);
    }
    if (!serviceEndpoint.equalsIgnoreCase(redirectUri)) {
        throw requestError("Unregistered redirect uri", caller, principal.getDomain(), principalDomain);
    }
    if (!ZTSConsts.ZTS_OPENID_RESPONSE_IT_ONLY.equals(responseType)) {
        return oidcError("invalid response type", redirectUri, state);
    }
    if (StringUtil.isEmpty(scope)) {
        return oidcError("no scope provided", redirectUri, state);
    }
    // our scopes are space separated list of values. Any groups
    // scopes are preferred over any role scopes
    IdTokenRequest tokenRequest = new IdTokenRequest(scope);
    if (tokenRequest.getDomainName() != null && !domainName.equalsIgnoreCase(tokenRequest.getDomainName())) {
        return oidcError("domain name mismatch", redirectUri, state);
    }
    // check if the authorized service domain matches to the
    // requested domain name
    checkRoleTokenAuthorizedServiceRequest(principal, domainName, caller);
    // validate principal object to make sure we're not
    // processing a role identity, and instead we require
    // a service identity
    validatePrincipalNotRoleIdentity(principal, caller);
    // now let's process our requests and see if we need to extract
    // either groups or roles for our response
    List<String> groups = null;
    if (tokenRequest.isGroupsScope()) {
        Set<String> groupNames = tokenRequest.getGroupNames();
        if (groupNames != null) {
            for (String groupName : groupNames) {
                validate(groupName, TYPE_ENTITY_NAME, principalDomain, caller);
            }
        }
        // process our request and retrieve the groups for the principal
        groups = dataStore.getPrincipalGroups(principalName, domainName, groupNames);
        if (groupNames != null && groups == null) {
            return oidcError("principal not included in requested groups", redirectUri, state);
        }
    } else if (tokenRequest.isRolesScope()) {
        String[] requestedRoles = tokenRequest.getRoleNames();
        if (requestedRoles != null) {
            for (String requestedRole : requestedRoles) {
                validate(requestedRole, TYPE_ENTITY_NAME, principalDomain, caller);
            }
        }
        // process our request and retrieve the roles for the principal
        Set<String> roles = new HashSet<>();
        dataStore.getAccessibleRoles(data, domainName, principalName, requestedRoles, roles, false);
        if (requestedRoles != null && roles.isEmpty()) {
            return oidcError("principal not included in requested roles", redirectUri, state);
        }
        groups = new ArrayList<>(roles);
    }
    long iat = System.currentTimeMillis() / 1000;
    IdToken idToken = new IdToken();
    idToken.setVersion(1);
    idToken.setAudience(clientId);
    idToken.setSubject(principalName);
    idToken.setIssuer(ztsOpenIDIssuer);
    idToken.setNonce(nonce);
    idToken.setGroups(groups);
    idToken.setIssueTime(iat);
    idToken.setAuthTime(iat);
    idToken.setExpiryTime(iat + idTokenDefaultTimeout);
    ServerPrivateKey signPrivateKey = getSignPrivateKey(keyType);
    String location = redirectUri + "#id_token=" + idToken.getSignedToken(signPrivateKey.getKey(), signPrivateKey.getId(), signPrivateKey.getAlgorithm());
    if (!StringUtil.isEmpty(state)) {
        location += "&state=" + state;
    }
    return Response.status(ResourceException.FOUND).header("Location", location).build();
}
Also used : IdToken(com.yahoo.athenz.auth.token.IdToken) IdTokenRequest(com.yahoo.athenz.zts.token.IdTokenRequest) DataCache(com.yahoo.athenz.zts.cache.DataCache) SimplePrincipal(com.yahoo.athenz.auth.impl.SimplePrincipal)

Aggregations

SimplePrincipal (com.yahoo.athenz.auth.impl.SimplePrincipal)1 IdToken (com.yahoo.athenz.auth.token.IdToken)1 DataCache (com.yahoo.athenz.zts.cache.DataCache)1 IdTokenRequest (com.yahoo.athenz.zts.token.IdTokenRequest)1