org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException Java Examples

The following examples show how to use org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: OAuthUtils.java    From cxf with Apache License 2.0 6 votes vote down vote up
public static List<String> getRequestedScopes(Client client,
                                              String scopeParameter,
                                              boolean useAllClientScopes,
                                              boolean partialMatchScopeValidation) {
    List<String> requestScopes = parseScope(scopeParameter);
    List<String> registeredScopes = client.getRegisteredScopes();
    if (requestScopes.isEmpty()) {
        return registeredScopes;
    }
    if (!validateScopes(requestScopes, registeredScopes, partialMatchScopeValidation)) {
        throw new OAuthServiceException("Unexpected scope");
    }
    if (useAllClientScopes) {
        for (String registeredScope : registeredScopes) {
            if (!requestScopes.contains(registeredScope)) {
                requestScopes.add(registeredScope);
            }
        }
    }

    return requestScopes;
}
 
Example #2
Source File: JAXRSOAuth2Test.java    From cxf with Apache License 2.0 6 votes vote down vote up
@Test
public void testSAMLAudRestr() throws Exception {
    String address = "https://localhost:" + port + "/oauth2-auth/token";
    WebClient wc = createWebClient(address);

    String audienceURI = "https://localhost:" + port + "/oauth2-auth/token2";
    String assertion = OAuth2TestUtils.createToken(audienceURI, true, true);
    String encodedAssertion = Base64UrlUtility.encode(assertion);

    Map<String, String> extraParams = new HashMap<>();
    extraParams.put(Constants.CLIENT_AUTH_ASSERTION_TYPE, Constants.CLIENT_AUTH_SAML2_BEARER);
    extraParams.put(Constants.CLIENT_AUTH_ASSERTION_PARAM, encodedAssertion);

    try {
        OAuthClientUtils.getAccessToken(wc, new CustomGrant(), extraParams);
        fail("Failure expected on a bad audience restriction");
    } catch (OAuthServiceException ex) {
        // expected
    }
}
 
Example #3
Source File: JAXRSOAuth2Test.java    From cxf with Apache License 2.0 6 votes vote down vote up
@Test
public void testBasicAuthClientCred() throws Exception {
    String address = "https://localhost:" + port + "/oauth2/token";
    WebClient wc = createWebClient(address);
    ClientCredentialsGrant grant = new ClientCredentialsGrant();
    // Pass client_id & client_secret as form properties
    // (instead WebClient can be initialized with username & password)
    grant.setClientId("bob");
    grant.setClientSecret("bobPassword");
    try {
        OAuthClientUtils.getAccessToken(wc, grant);
        fail("Form based authentication is not supported");
    } catch (OAuthServiceException ex) {
        assertEquals(OAuthConstants.UNAUTHORIZED_CLIENT, ex.getError().getError());
    }

    ClientAccessToken at = OAuthClientUtils.getAccessToken(wc,
                                                           new Consumer("bob", "bobPassword"),
                                                           new ClientCredentialsGrant(),
                                                           true);
    assertNotNull(at.getTokenKey());
}
 
Example #4
Source File: JAXRSOAuth2Test.java    From cxf with Apache License 2.0 6 votes vote down vote up
@Test
public void testJWTBadSubjectName() throws Exception {
    String address = "https://localhost:" + port + "/oauth2-auth-jwt/token";
    WebClient wc = createWebClient(address);

    // Create the JWT Token
    String token = OAuth2TestUtils.createToken("resourceOwner", "bob", address, true, true);

    Map<String, String> extraParams = new HashMap<>();
    extraParams.put(Constants.CLIENT_AUTH_ASSERTION_TYPE,
                    "urn:ietf:params:oauth:client-assertion-type:jwt-bearer");
    extraParams.put(Constants.CLIENT_AUTH_ASSERTION_PARAM, token);

    try {
        OAuthClientUtils.getAccessToken(wc, new CustomGrant(), extraParams);
        fail("Failure expected on a bad subject name");
    } catch (OAuthServiceException ex) {
        // expected
    }
}
 
Example #5
Source File: OidcAuthorizationCodeService.java    From cxf with Apache License 2.0 6 votes vote down vote up
@Override
protected boolean canAuthorizationBeSkipped(MultivaluedMap<String, String> params,
                                            Client client,
                                            UserSubject userSubject,
                                            List<String> requestedScope,
                                            List<OAuthPermission> permissions) {
    List<String> promptValues = OidcUtils.getPromptValues(params);
    if (promptValues.contains(OidcUtils.PROMPT_CONSENT_VALUE)) {
        // Displaying the consent screen is preferred by the client
        return false;
    }
    // Check the pre-configured consent
    boolean preConfiguredConsentForScopes =
        super.canAuthorizationBeSkipped(params, client, userSubject, requestedScope, permissions);

    if (!preConfiguredConsentForScopes && promptValues.contains(OidcUtils.PROMPT_NONE_VALUE)) {
        // An error is returned if client does not have pre-configured consent for the requested scopes/claims
        LOG.log(Level.FINE, "Prompt 'none' request can not be met");
        throw new OAuthServiceException(new OAuthError(OidcUtils.CONSENT_REQUIRED_ERROR));
    }
    return preConfiguredConsentForScopes;
}
 
Example #6
Source File: AbstractGrantHandler.java    From cxf with Apache License 2.0 6 votes vote down vote up
protected ServerAccessToken getPreAuthorizedToken(Client client,
                                                  UserSubject subject,
                                                  String requestedGrant,
                                                  List<String> requestedScopes,
                                                  List<String> audiences) {
    if (!OAuthUtils.validateScopes(requestedScopes, client.getRegisteredScopes(),
                                   partialMatchScopeValidation)) {
        throw new OAuthServiceException(new OAuthError(OAuthConstants.INVALID_SCOPE));
    }
    if (!OAuthUtils.validateAudiences(audiences, client.getRegisteredAudiences())) {
        throw new OAuthServiceException(new OAuthError(OAuthConstants.INVALID_GRANT));
    }

    // Get a pre-authorized token if available
    return dataProvider.getPreauthorizedToken(
                                 client, requestedScopes, subject, requestedGrant);

}
 
Example #7
Source File: OidcUtils.java    From cxf with Apache License 2.0 6 votes vote down vote up
private static String calculateHash(String value, SignatureAlgorithm sigAlgo) {
    if (sigAlgo == SignatureAlgorithm.NONE) {
        throw new JwsException(JwsException.Error.INVALID_ALGORITHM);
    }
    String algoShaSizeString = sigAlgo.getJwaName().substring(2);
    String javaShaAlgo = "SHA-" + algoShaSizeString;
    int algoShaSize = Integer.parseInt(algoShaSizeString);
    int valueHashSize = (algoShaSize / 8) / 2;
    try {
        byte[] atBytes = StringUtils.toBytesASCII(value);
        byte[] digest = MessageDigestUtils.createDigest(atBytes,  javaShaAlgo);
        return Base64UrlUtility.encodeChunk(digest, 0, valueHashSize);
    } catch (NoSuchAlgorithmException ex) {
        throw new OAuthServiceException(ex);
    }
}
 
Example #8
Source File: OidcImplicitService.java    From cxf with Apache License 2.0 6 votes vote down vote up
@Override
protected boolean canAuthorizationBeSkipped(MultivaluedMap<String, String> params,
                                            Client client,
                                            UserSubject userSubject,
                                            List<String> requestedScope,
                                            List<OAuthPermission> permissions) {
    List<String> promptValues = OidcUtils.getPromptValues(params);
    if (promptValues.contains(OidcUtils.PROMPT_CONSENT_VALUE)) {
        // Displaying the consent screen is preferred by the client
        return false;
    }
    // Check the pre-configured consent
    boolean preConfiguredConsentForScopes =
        super.canAuthorizationBeSkipped(params, client, userSubject, requestedScope, permissions);

    if (!preConfiguredConsentForScopes && promptValues.contains(OidcUtils.PROMPT_NONE_VALUE)) {
        // An error is returned if client does not have pre-configured consent for the requested scopes/claims
        LOG.log(Level.FINE, "Prompt 'none' request can not be met");
        throw new OAuthServiceException(new OAuthError(OidcUtils.CONSENT_REQUIRED_ERROR));
    }
    return preConfiguredConsentForScopes;
}
 
Example #9
Source File: OAuthUtils.java    From cxf with Apache License 2.0 6 votes vote down vote up
public static SignatureAlgorithm getClientSecretSignatureAlgorithm(Properties sigProps) {

        String clientSecretSigProp = sigProps.getProperty(OAuthConstants.CLIENT_SECRET_SIGNATURE_ALGORITHM);
        if (clientSecretSigProp == null) {
            String sigProp = sigProps.getProperty(JoseConstants.RSSEC_SIGNATURE_ALGORITHM);
            if (AlgorithmUtils.isHmacSign(sigProp)) {
                clientSecretSigProp = sigProp;
            }
        }
        SignatureAlgorithm sigAlgo = SignatureAlgorithm.getAlgorithm(clientSecretSigProp);
        sigAlgo = sigAlgo != null ? sigAlgo : SignatureAlgorithm.HS256;
        if (!AlgorithmUtils.isHmacSign(sigAlgo)) {
            // Must be HS-based for the symmetric signature
            throw new OAuthServiceException(OAuthConstants.SERVER_ERROR);
        }
        return sigAlgo;
    }
 
Example #10
Source File: HawkAccessTokenValidatorClient.java    From cxf with Apache License 2.0 6 votes vote down vote up
public AccessTokenValidation validateAccessToken(MessageContext mc,
                                                 String authScheme,
                                                 String authSchemeData,
                                                 MultivaluedMap<String, String> extraProps)
    throws OAuthServiceException {
    if (isRemoteSignatureValidation()) {
        MultivaluedMap<String, String> map = new MetadataMap<>();
        if (extraProps != null) {
            map.putAll(extraProps);
        }
        map.putSingle(HTTP_VERB, mc.getRequest().getMethod());
        map.putSingle(HTTP_URI, mc.getUriInfo().getRequestUri().toString());
        return validator.validateAccessToken(mc, authScheme, authSchemeData, map);
    }
    return super.validateAccessToken(mc, authScheme, authSchemeData, extraProps);

}
 
Example #11
Source File: AccessTokenValidatorClient.java    From cxf with Apache License 2.0 6 votes vote down vote up
public AccessTokenValidation validateAccessToken(MessageContext mc,
                                                 String authScheme,
                                                 String authSchemeData,
                                                 MultivaluedMap<String, String> extraProps)
    throws OAuthServiceException {
    WebClient client = WebClient.fromClient(tokenValidatorClient, true);
    MultivaluedMap<String, String> props = new MetadataMap<>();
    props.putSingle(OAuthConstants.AUTHORIZATION_SCHEME_TYPE, authScheme);
    props.putSingle(OAuthConstants.AUTHORIZATION_SCHEME_DATA, authSchemeData);
    if (extraProps != null) {
        props.putAll(extraProps);
    }
    try {
        return client.post(props, AccessTokenValidation.class);
    } catch (WebApplicationException ex) {
        throw new OAuthServiceException(ex);
    }
}
 
Example #12
Source File: DirectAuthorizationService.java    From cxf with Apache License 2.0 6 votes vote down vote up
protected Client getClient(MultivaluedMap<String, String> params) {
    Client client = null;

    try {
        client = getValidClient(params.getFirst(OAuthConstants.CLIENT_ID), params);
    } catch (OAuthServiceException ex) {
        if (ex.getError() != null) {
            reportInvalidRequestError(ex.getError(), null);
        }
    }

    if (client == null) {
        reportInvalidRequestError("Client ID is invalid", null);
    }
    return client;

}
 
Example #13
Source File: OAuthClientUtils.java    From cxf with Apache License 2.0 6 votes vote down vote up
private static void appendTokenData(StringBuilder sb,
                                    ClientAccessToken token,
                                    HttpRequestProperties httpProps)
    throws OAuthServiceException {
    // this should all be handled by token specific serializers
    String tokenType = token.getTokenType().toLowerCase();
    if (OAuthConstants.BEARER_TOKEN_TYPE.equalsIgnoreCase(tokenType)) {
        sb.append(OAuthConstants.BEARER_AUTHORIZATION_SCHEME);
        sb.append(' ');
        sb.append(token.getTokenKey());
    } else if (OAuthConstants.HAWK_TOKEN_TYPE.equalsIgnoreCase(tokenType)) {
        if (httpProps == null) {
            throw new IllegalArgumentException("MAC scheme requires HTTP Request properties");
        }
        HawkAuthorizationScheme macAuthData = new HawkAuthorizationScheme(httpProps, token);
        String macAlgo = token.getParameters().get(OAuthConstants.HAWK_TOKEN_ALGORITHM);
        String macKey = token.getParameters().get(OAuthConstants.HAWK_TOKEN_KEY);
        sb.append(macAuthData.toAuthorizationHeader(macAlgo, macKey));
    } else {
        throw new ProcessingException(new OAuthServiceException("Unsupported token type"));
    }

}
 
Example #14
Source File: RedirectionBasedGrantService.java    From cxf with Apache License 2.0 6 votes vote down vote up
/**
 * Get the {@link Client} reference
 * @param params request parameters
 * @return Client the client reference
 * @throws {@link javax.ws.rs.WebApplicationException} if no matching Client is found,
 *         the error is returned directly to the end user without
 *         following the redirect URI if any
 */
protected Client getClient(String clientId, MultivaluedMap<String, String> params) {
    Client client = null;

    try {
        client = getValidClient(clientId, params);
    } catch (OAuthServiceException ex) {
        if (ex.getError() != null) {
            reportInvalidRequestError(ex.getError(), null);
        }
    }

    if (client == null) {
        reportInvalidRequestError("Client ID is invalid", null);
    }
    return client;

}
 
Example #15
Source File: FedizSubjectCreator.java    From cxf-fediz with Apache License 2.0 6 votes vote down vote up
@Override
public OidcUserSubject createUserSubject(MessageContext mc, MultivaluedMap<String, String> params) {
    Principal principal = mc.getSecurityContext().getUserPrincipal();

    if (!(principal instanceof FedizPrincipal)) {
        throw new OAuthServiceException("Unsupported Principal");
    }
    FedizPrincipal fedizPrincipal = (FedizPrincipal) principal;

    // In the future FedizPrincipal will likely have JWT claims already prepared,
    // with IdToken being initialized here from those claims
    OidcUserSubject oidcSub = new OidcUserSubject();
    oidcSub.setLogin(fedizPrincipal.getName());

    // REVISIT: use fedizPrincipal.getId() to guarantee the uniqueness once FEDIZ-207 is resolved
    oidcSub.setId(fedizPrincipal.getName());

    IdToken idToken = convertToIdToken(mc, fedizPrincipal.getLoginToken(), oidcSub.getLogin(), oidcSub.getId(),
            fedizPrincipal.getClaims(), fedizPrincipal.getRoleClaims(), params);
    oidcSub.setIdToken(idToken);
    oidcSub.setRoles(fedizPrincipal.getRoleClaims());
    // UserInfo can be populated and set on OidcUserSubject too.
    // UserInfoService will create it otherwise.

    return oidcSub;
}
 
Example #16
Source File: NonceVerifierImplTest.java    From cxf with Apache License 2.0 6 votes vote down vote up
@Test
public void testVerifyNonceInvalidTimestamp() {
    long now = System.currentTimeMillis();
    Nonce nonce1 = new Nonce("nonce1", now - 2000); // first request 2 seconds back
    Nonce nonce2 = new Nonce("nonce2", now - 1000); // second request 1 second back
    NonceHistory nonceHistory = new NonceHistory(200, nonce1); // first request time delta is 200ms
    nonceHistory.addNonce(nonce2);

    EasyMock.expect(nonceStore.getNonceHistory("testTokenKey")).andReturn(nonceHistory);
    EasyMock.replay(nonceStore);
    nonceVerifier.setAllowedWindow(2000); // allowed window is 2 seconds
    try {
        nonceVerifier.verifyNonce("testTokenKey", "nonce3", Long.toString(now - 5000)); // very old timestamp
        fail("Exception expected");
    } catch (OAuthServiceException ex) {
        assertEquals("Timestamp is invalid", ex.getMessage());
    }
}
 
Example #17
Source File: EHCacheOIDCTokenProvider.java    From cxf-fediz with Apache License 2.0 6 votes vote down vote up
@Override
public List<OAuthPermission> convertScopeToPermissions(Client client, List<String> requestedScopes) {
    if (requestedScopes.isEmpty()) {
        return Collections.emptyList();
    }

    List<OAuthPermission> permissions = new ArrayList<>();
    for (String requestedScope : requestedScopes) {
        if ("openid".equals(requestedScope)) {
            OAuthPermission permission = new OAuthPermission("openid", "Authenticate user");
            permissions.add(permission);
        } else {
            throw new OAuthServiceException("invalid_scope");
        }
    }

    return permissions;
}
 
Example #18
Source File: AbstractTokenService.java    From cxf with Apache License 2.0 5 votes vote down vote up
protected Response handleException(OAuthServiceException ex, String error) {
    OAuthError customError = ex.getError();
    if (writeCustomErrors && customError != null) {
        return createErrorResponseFromBean(customError);
    }
    return createErrorResponseFromBean(new OAuthError(error));
}
 
Example #19
Source File: UserInfoClient.java    From cxf with Apache License 2.0 5 votes vote down vote up
public void validateUserInfo(UserInfo profile, IdToken idToken, Consumer client) {
    validateJwtClaims(profile, client.getClientId(), false);
    // validate subject
    if (!idToken.getSubject().equals(profile.getSubject())) {
        throw new OAuthServiceException("Invalid subject");
    }
}
 
Example #20
Source File: OidcUtils.java    From cxf with Apache License 2.0 5 votes vote down vote up
public static void validateCodeHash(String code, JwtToken jwt, boolean required) {
    String hashClaim = (String)jwt.getClaims().getClaim(IdToken.AUTH_CODE_HASH_CLAIM);
    if (hashClaim == null && required) {
        throw new OAuthServiceException("Invalid hash");
    }
    if (hashClaim != null) {
        validateHash(code,
                     (String)jwt.getClaims().getClaim(IdToken.AUTH_CODE_HASH_CLAIM),
                     jwt.getJwsHeaders().getSignatureAlgorithm());
    }
}
 
Example #21
Source File: OAuthUtils.java    From cxf with Apache License 2.0 5 votes vote down vote up
public static void setCertificateThumbprintConfirmation(MessageContext mc, X509Certificate cert) {
    try {
        byte[] thumbprint = createCertificateThumbprint(cert);
        String encodedThumbprint = Base64UrlUtility.encode(thumbprint);
        mc.put(JoseConstants.HEADER_X509_THUMBPRINT_SHA256, encodedThumbprint);
    } catch (Exception ex) {
        throw new OAuthServiceException(ex);
    }
}
 
Example #22
Source File: EncryptingDataProvider.java    From cxf with Apache License 2.0 5 votes vote down vote up
@Override
public ServerAccessToken refreshAccessToken(Client client, String refreshToken,
                                            List<String> requestedScopes)
    throws OAuthServiceException {
    String encrypted = refreshTokens.remove(refreshToken);
    ServerAccessToken token = ModelEncryptionSupport.decryptAccessToken(this, encrypted, key);
    tokens.remove(token.getTokenKey());

    // create a new refresh token
    createRefreshToken(token);
    // possibly update other token properties
    encryptAccessToken(token);

    return token;
}
 
Example #23
Source File: OidcClientCodeRequestFilter.java    From cxf with Apache License 2.0 5 votes vote down vote up
@Override
protected ClientTokenContext createTokenContext(ContainerRequestContext rc,
                                                ClientAccessToken at,
                                                MultivaluedMap<String, String> requestParams,
                                                MultivaluedMap<String, String> state) {
    if (rc.getSecurityContext() instanceof OidcSecurityContext) {
        return ((OidcSecurityContext)rc.getSecurityContext()).getOidcContext();
    }
    OidcClientTokenContextImpl ctx = new OidcClientTokenContextImpl();
    if (at != null) {
        if (idTokenReader == null) {
            throw new OAuthServiceException(OAuthConstants.SERVER_ERROR);
        }
        IdToken idToken = idTokenReader.getIdToken(at,
                              requestParams.getFirst(OAuthConstants.AUTHORIZATION_CODE_VALUE),
                              getConsumer());
        // Validate the properties set up at the redirection time.
        validateIdToken(idToken, state);

        ctx.setIdToken(idToken);
        if (userInfoClient != null) {
            ctx.setUserInfo(userInfoClient.getUserInfo(at,
                                                       ctx.getIdToken(),
                                                       getConsumer()));
        }
        OidcSecurityContext oidcSecCtx = new OidcSecurityContext(ctx);
        oidcSecCtx.setRoleClaim(roleClaim);
        rc.setSecurityContext(oidcSecCtx);
    }

    return ctx;
}
 
Example #24
Source File: FedizSubjectCreator.java    From cxf-fediz with Apache License 2.0 5 votes vote down vote up
private Assertion getSaml2Assertion(Element samlToken) {
    // Should a null assertion lead to the exception ?
    try {
        SamlAssertionWrapper wrapper = new SamlAssertionWrapper(samlToken);
        return wrapper.getSaml2();
    } catch (WSSecurityException ex) {
        throw new OAuthServiceException("Error converting SAML token", ex);
    }

}
 
Example #25
Source File: JCacheCodeDataProvider.java    From cxf with Apache License 2.0 5 votes vote down vote up
@Override
public ServerAuthorizationCodeGrant removeCodeGrant(String code) throws OAuthServiceException {
    ServerAuthorizationCodeGrant grant = getCodeGrant(code);
    if (grant != null) {
        grantCache.remove(code);
    }
    return grant;
}
 
Example #26
Source File: JCacheCodeDataProvider.java    From cxf with Apache License 2.0 5 votes vote down vote up
@Override
public ServerAuthorizationCodeGrant createCodeGrant(AuthorizationCodeRegistration reg)
    throws OAuthServiceException {
    ServerAuthorizationCodeGrant grant = AbstractCodeDataProvider.initCodeGrant(reg, codeLifetime);
    grantCache.put(grant.getCode(), grant);

    return grant;
}
 
Example #27
Source File: AbstractAuthorizationCodeDataProvider.java    From cxf with Apache License 2.0 5 votes vote down vote up
public ServerAuthorizationCodeGrant createCodeGrant(AuthorizationCodeRegistration reg)
    throws OAuthServiceException {
    ServerAuthorizationCodeGrant grant =
        new ServerAuthorizationCodeGrant(reg.getClient(), getCode(reg), getGrantLifetime(), getIssuedAt());
    grant.setApprovedScopes(getApprovedScopes(reg));
    grant.setAudience(reg.getAudience());
    grant.setClientCodeChallenge(reg.getClientCodeChallenge());
    grant.setSubject(reg.getSubject());
    grant.setRedirectUri(reg.getRedirectUri());
    return grant;
}
 
Example #28
Source File: OAuthClientUtils.java    From cxf with Apache License 2.0 5 votes vote down vote up
/**
 * Obtains the access token from OAuth AccessToken Service
 * @param accessTokenServiceUri the AccessToken endpoint address
 * @param consumer {@link Consumer} representing the registered client
 * @param grant {@link AccessTokenGrant} grant
 * @param setAuthorizationHeader if set to true then HTTP Basic scheme
 *           will be used to pass client id and secret, otherwise they will
 *           be passed in the form payload
 * @return {@link ClientAccessToken} access token
 * @throws OAuthServiceException
 */
public static ClientAccessToken getAccessToken(String accessTokenServiceUri,
                                               Consumer consumer,
                                               AccessTokenGrant grant,
                                               boolean setAuthorizationHeader)
    throws OAuthServiceException {
    OAuthJSONProvider provider = new OAuthJSONProvider();
    WebClient accessTokenService =
        WebClient.create(accessTokenServiceUri, Collections.singletonList(provider));
    accessTokenService.accept("application/json");
    return getAccessToken(accessTokenService, consumer, grant, setAuthorizationHeader);
}
 
Example #29
Source File: OAuthDataProviderImpl.java    From cxf-fediz with Apache License 2.0 5 votes vote down vote up
@Override
protected void checkRequestedScopes(Client client, List<String> requestedScopes) {
    String grantType = super.getCurrentRequestedGrantType();
    if (grantType != null && !NON_REDIRECTION_FLOWS.contains(grantType)    
        && !requestedScopes.contains(OidcUtils.OPENID_SCOPE)) {
        throw new OAuthServiceException("Required scopes are missing");
    }
}
 
Example #30
Source File: AbstractCodeDataProvider.java    From cxf with Apache License 2.0 5 votes vote down vote up
@Override
public ServerAuthorizationCodeGrant createCodeGrant(AuthorizationCodeRegistration reg)
    throws OAuthServiceException {
    ServerAuthorizationCodeGrant grant = doCreateCodeGrant(reg);
    saveCodeGrant(grant);
    return grant;
}