Search in sources :

Example 1 with OAuthDelegatedTokenEntity

use of com.peterphi.usermanager.db.entity.OAuthDelegatedTokenEntity in project stdlib by petergeneric.

the class UserManagerOAuthServiceImpl method get.

@Override
@Transactional(readOnly = true)
@AuthConstraint(id = "oauth2server_token_to_userinfo", skip = true)
public UserManagerUser get(final String token, final String clientId) {
    if (UserManagerBearerToken.isUserManagerDelegatedBearer(token)) {
        final String delegatedTokenId = token.substring(UserManagerBearerToken.PREFIX_DELEGATED.length());
        final OAuthDelegatedTokenEntity delegated = delegatedTokenDao.getByIdUnlessExpired(delegatedTokenId);
        if (delegated == null)
            throw new IllegalArgumentException("Delegated Token provided is invalid or has expired!");
        final UserEntity user = delegated.getSession().getContext().getUser();
        UserManagerUser obj = marshaller.marshal(user);
        obj.delegated = true;
        obj.originService = delegated.getSession().getContext().getService().getId();
        // Expose the service in communication with the user as a role too for legacy clients
        obj.roles.add("origin_" + obj.originService);
        obj.roles.add(CurrentUser.ROLE_DELEGATED);
        obj.roles.add(CurrentUser.ROLE_SERVICE_CALL);
        // Add the service's roles too
        for (RoleEntity serviceRole : delegated.getSession().getContext().getService().getRoles()) {
            obj.roles.add(serviceRole.getId());
        }
        return obj;
    } else if (UserManagerBearerToken.isUserManagerServiceBearer(token)) {
        final OAuthServiceEntity serviceUser = serviceDao.getByAccessKey(token);
        if (serviceUser == null)
            throw new IllegalArgumentException("Service Access Key not recognised");
        UserEntity fakeUser = new UserEntity();
        fakeUser.setName(serviceUser.getId());
        fakeUser.setEmail(serviceUser.getId() + "@service.localhost");
        fakeUser.setLocal(true);
        fakeUser.setRoles(new ArrayList<>(serviceUser.getRoles()));
        fakeUser.setTimeZone(CurrentUser.DEFAULT_TIMEZONE);
        fakeUser.setDateFormat(CurrentUser.ISO_DATE_FORMAT_STRING);
        UserManagerUser obj = marshaller.marshal(fakeUser);
        obj.service = true;
        obj.delegated = false;
        obj.roles.add(CurrentUser.ROLE_SERVICE_CALL);
        return obj;
    } else {
        final OAuthSessionEntity session = getSessionForToken(token, clientId);
        return marshaller.marshal(session.getContext().getUser());
    }
}
Also used : RoleEntity(com.peterphi.usermanager.db.entity.RoleEntity) OAuthDelegatedTokenEntity(com.peterphi.usermanager.db.entity.OAuthDelegatedTokenEntity) OAuthSessionEntity(com.peterphi.usermanager.db.entity.OAuthSessionEntity) OAuthServiceEntity(com.peterphi.usermanager.db.entity.OAuthServiceEntity) UserManagerUser(com.peterphi.usermanager.rest.type.UserManagerUser) ArrayList(java.util.ArrayList) UserEntity(com.peterphi.usermanager.db.entity.UserEntity) AuthConstraint(com.peterphi.std.guice.common.auth.annotations.AuthConstraint) Transactional(com.peterphi.std.guice.database.annotation.Transactional)

Example 2 with OAuthDelegatedTokenEntity

use of com.peterphi.usermanager.db.entity.OAuthDelegatedTokenEntity in project stdlib by petergeneric.

the class UserManagerOAuthServiceImpl method getToken.

@Override
@Transactional
@AuthConstraint(id = "oauth2server_token", skip = true)
public String getToken(final String grantType, final String code, final String redirectUri, String clientId, String secret, final String refreshToken, final String username, final String password, final String subjectToken, final String authorizationHeader) {
    OAuthSessionEntity session;
    // Allow clients to supply their ID and Secret using Basic Auth (per RFC)
    if (StringUtils.isNotEmpty(authorizationHeader) && StringUtils.isEmpty(clientId) && StringUtils.isEmpty(secret)) {
        // N.B. returns null if not BASIC auth (e.g. Bearer auth)
        final String[] credentials = BasicAuthHelper.parseHeader(authorizationHeader);
        if (credentials != null) {
            clientId = credentials[0];
            secret = credentials[1];
        }
    }
    switch(grantType) {
        case GRANT_TYPE_AUTHORIZATION_CODE:
            {
                final OAuthServiceEntity service = serviceDao.getByClientIdAndSecretAndEndpoint(clientId, secret, redirectUri);
                if (service == null)
                    throw new IllegalArgumentException("One or more of OAuth Client's Client ID / Client Secret / Redirect URI were not valid");
                session = sessionDao.exchangeCodeForToken(service, code);
                if (session == null)
                    throw new IllegalArgumentException("Unable to exchange authorisation code for a token!");
                break;
            }
        case GRANT_TYPE_REFRESH_TOKEN:
            {
                if (UserManagerBearerToken.isUserManagerServiceBearer(refreshToken)) {
                    // This is necessary because a Service User isn't a real user and so can't have a Session
                    return getToken(GRANT_TYPE_TOKEN_EXCHANGE, code, redirectUri, clientId, secret, null, username, password, // Use provided refresh token as the subject token for new invocation
                    refreshToken, authorizationHeader);
                } else {
                    // Regular refresh token
                    final OAuthServiceEntity service = serviceDao.getByClientIdAndSecretAndEndpoint(clientId, secret, redirectUri);
                    if (service == null)
                        throw new IllegalArgumentException("One or more of OAuth Client's Client ID / Client Secret / Redirect URI were not valid");
                    session = sessionDao.exchangeRefreshTokenForNewToken(service, refreshToken, new DateTime().plus(tokenRefreshInterval));
                    if (session == null)
                        throw new IllegalArgumentException("Unable to exchange refresh token for a token!");
                    break;
                }
            }
        case GRANT_TYPE_PASSWORD:
            {
                // N.B. Don't expect the clientSecret from this call
                final UserEntity user = userDao.login(username, password);
                if (user == null)
                    throw new IllegalArgumentException("Incorrect username/password combination");
                // Accept the use of the service and create a new session
                session = createSession(user.getId(), clientId, redirectUri, "password-to-token", true);
                // Take the authorisation code internally and exchange it for a token
                session = sessionDao.exchangeCodeForToken(session.getContext().getService(), session.getAuthorisationCode());
                if (session == null)
                    throw new IllegalArgumentException("Unable to exchange username/password for a token!");
                break;
            }
        case GRANT_TYPE_TOKEN_EXCHANGE:
            {
                final OAuthServiceEntity service = serviceDao.getByClientIdAndSecretAndEndpoint(clientId, secret, redirectUri);
                if (service == null)
                    throw new IllegalArgumentException("One or more of OAuth Client's Client ID / Client Secret / Redirect URI were not valid");
                if (UserManagerBearerToken.isUserManagerDelegatedBearer(subjectToken)) {
                    final String delegatedTokenId = subjectToken.substring(UserManagerBearerToken.PREFIX_DELEGATED.length());
                    OAuthDelegatedTokenEntity delegated = delegatedTokenDao.getByIdUnlessExpired(delegatedTokenId);
                    if (delegated == null)
                        throw new IllegalArgumentException("Delegated Token ID invalid, expired or refers to expired or invalidated Session!");
                    // Return a fake session reference
                    return new OAuth2TokenResponse(subjectToken, null, delegated.getExpires().toDate()).encode();
                } else if (UserManagerBearerToken.isUserManagerServiceBearer(subjectToken)) {
                    final OAuthServiceEntity serviceUser = serviceDao.getByAccessKey(subjectToken);
                    if (serviceUser == null)
                        throw new IllegalArgumentException("Service Access Key not recognised");
                    // N.B. refresh token is the same as this token, which will cause this logic to run again on refresh
                    return new OAuth2TokenResponse(subjectToken, subjectToken, new DateTime().plus(tokenRefreshInterval).toDate()).encode();
                } else {
                    final UserEntity user = userDao.loginByAccessKey(subjectToken);
                    if (user == null)
                        throw new IllegalArgumentException("Access Key not recognised");
                    // Accept the use of the service and create a new session
                    // N.B. do not allow token exchange to be used to gain access to a service this user has not explicitly granted
                    session = createSession(user.getId(), clientId, redirectUri, GRANT_TYPE_TOKEN_EXCHANGE, autoGrantAccessKeysToAccessAllServices);
                    if (session == null)
                        throw new IllegalArgumentException("The User associated with this Access Key (" + user.getName() + ") has not approved access to this service yet");
                    // Take the authorisation code internally and exchange it for a token
                    session = sessionDao.exchangeCodeForToken(session.getContext().getService(), session.getAuthorisationCode());
                    if (session == null)
                        throw new IllegalArgumentException("Unable to exchange token!");
                }
                break;
            }
        case GRANT_TYPE_CLIENT_CREDENTIALS:
        default:
            {
                throw new IllegalArgumentException("unsupported grant_type: " + grantType);
            }
    }
    if (session == null)
        throw new IllegalArgumentException("Unable to acquire token.");
    return new OAuth2TokenResponse(session.getToken(), session.getId(), session.getExpires().toDate()).encode();
}
Also used : OAuthDelegatedTokenEntity(com.peterphi.usermanager.db.entity.OAuthDelegatedTokenEntity) OAuth2TokenResponse(com.peterphi.usermanager.rest.iface.oauth2server.types.OAuth2TokenResponse) OAuthSessionEntity(com.peterphi.usermanager.db.entity.OAuthSessionEntity) OAuthServiceEntity(com.peterphi.usermanager.db.entity.OAuthServiceEntity) DateTime(org.joda.time.DateTime) UserEntity(com.peterphi.usermanager.db.entity.UserEntity) AuthConstraint(com.peterphi.std.guice.common.auth.annotations.AuthConstraint) Transactional(com.peterphi.std.guice.database.annotation.Transactional)

Example 3 with OAuthDelegatedTokenEntity

use of com.peterphi.usermanager.db.entity.OAuthDelegatedTokenEntity in project stdlib by petergeneric.

the class DeleteExpiredSessionDaemon method deleteExpiredDelegatedTokens.

@Transactional
public int deleteExpiredDelegatedTokens() {
    List<OAuthDelegatedTokenEntity> list = delegatedTokenDao.find(findExpiredDelegatedTokens()).getList();
    setTextState("Deleting " + list.size() + " expired delegated tokens");
    for (OAuthDelegatedTokenEntity entity : list) {
        delegatedTokenDao.delete(entity);
    }
    return list.size();
}
Also used : OAuthDelegatedTokenEntity(com.peterphi.usermanager.db.entity.OAuthDelegatedTokenEntity) Transactional(com.peterphi.std.guice.database.annotation.Transactional)

Example 4 with OAuthDelegatedTokenEntity

use of com.peterphi.usermanager.db.entity.OAuthDelegatedTokenEntity in project stdlib by petergeneric.

the class UserManagerOAuthServiceImpl method createDelegatedAccessToken.

@Override
@Transactional
@AuthConstraint(id = "oauth2server_token", skip = true)
public String createDelegatedAccessToken(String clientId, String secret, final long validityPeriod, final String refreshToken, final String authorizationHeader) {
    if (validityPeriod > Integer.MAX_VALUE)
        throw new IllegalArgumentException("Validity period too long!");
    // Allow clients to supply their ID and Secret using Basic Auth (per RFC)
    if (StringUtils.isNotEmpty(authorizationHeader) && StringUtils.isEmpty(clientId) && StringUtils.isEmpty(secret)) {
        // N.B. returns null if not BASIC auth (e.g. Bearer auth)
        final String[] credentials = BasicAuthHelper.parseHeader(authorizationHeader);
        if (credentials != null) {
            clientId = credentials[0];
            secret = credentials[1];
        }
    }
    final OAuthServiceEntity service = serviceDao.getByClientIdAndSecretOnly(clientId, secret);
    if (service == null)
        throw new IllegalArgumentException("One or more of OAuth Client's Client ID / Client Secret / Redirect URI were not valid");
    final OAuthSessionEntity session = sessionDao.getSessionToDelegateByRefreshToken(service, refreshToken);
    if (session == null)
        throw new IllegalArgumentException("Refresh Token provided is no longer valid!");
    final DateTime expires = DateTime.now().plusMillis((int) validityPeriod);
    final OAuthDelegatedTokenEntity delegatedToken = delegatedTokenDao.create(session, expires);
    // Return the delegated token as a User Manager Bearer Token (opaque to the client service)
    return UserManagerBearerToken.PREFIX_DELEGATED + delegatedToken.getId();
}
Also used : OAuthDelegatedTokenEntity(com.peterphi.usermanager.db.entity.OAuthDelegatedTokenEntity) OAuthSessionEntity(com.peterphi.usermanager.db.entity.OAuthSessionEntity) OAuthServiceEntity(com.peterphi.usermanager.db.entity.OAuthServiceEntity) DateTime(org.joda.time.DateTime) AuthConstraint(com.peterphi.std.guice.common.auth.annotations.AuthConstraint) Transactional(com.peterphi.std.guice.database.annotation.Transactional)

Example 5 with OAuthDelegatedTokenEntity

use of com.peterphi.usermanager.db.entity.OAuthDelegatedTokenEntity in project stdlib by petergeneric.

the class OAuthDelegatedTokenDaoImpl method create.

public OAuthDelegatedTokenEntity create(final OAuthSessionEntity session, final DateTime expires) {
    OAuthDelegatedTokenEntity entity = new OAuthDelegatedTokenEntity();
    entity.setSession(session);
    entity.setExpires(expires);
    save(entity);
    return entity;
}
Also used : OAuthDelegatedTokenEntity(com.peterphi.usermanager.db.entity.OAuthDelegatedTokenEntity)

Aggregations

OAuthDelegatedTokenEntity (com.peterphi.usermanager.db.entity.OAuthDelegatedTokenEntity)5 Transactional (com.peterphi.std.guice.database.annotation.Transactional)4 AuthConstraint (com.peterphi.std.guice.common.auth.annotations.AuthConstraint)3 OAuthServiceEntity (com.peterphi.usermanager.db.entity.OAuthServiceEntity)3 OAuthSessionEntity (com.peterphi.usermanager.db.entity.OAuthSessionEntity)3 UserEntity (com.peterphi.usermanager.db.entity.UserEntity)2 DateTime (org.joda.time.DateTime)2 RoleEntity (com.peterphi.usermanager.db.entity.RoleEntity)1 OAuth2TokenResponse (com.peterphi.usermanager.rest.iface.oauth2server.types.OAuth2TokenResponse)1 UserManagerUser (com.peterphi.usermanager.rest.type.UserManagerUser)1 ArrayList (java.util.ArrayList)1