class PasswordCredentialsGrantTypeHandler extends GrantTypeHandler {

    public AccessToken handle(OAuth2Request request, ClientRegistration clientRegistration,
            OAuth2ProviderSettings providerSettings) throws InvalidClientException,
            InvalidRequestException, UnauthorizedClientException, InvalidGrantException, ServerException,
            InvalidScopeException, NotFoundException {

        for (final PasswordCredentialsRequestValidator requestValidator : requestValidators) {
            requestValidator.validateRequest(request, clientRegistration);
        }

        final ResourceOwner resourceOwner = resourceOwnerAuthenticator.authenticate(request, false);
        if (resourceOwner == null) {
            logger.error("Unable to verify user");
            throw new InvalidGrantException();
        }

        final Set<String> scope = Utils.splitScope(request.<String>getParameter(SCOPE));
        final Set<String> validatedScope = providerSettings.validateAccessTokenScope(clientRegistration, scope,
                request);

        final String validatedClaims = providerSettings.validateRequestedClaims(
                (String) request.getParameter(OAuth2Constants.Custom.CLAIMS));

        final String grantType = request.getParameter(GRANT_TYPE);

        RefreshToken refreshToken = null;
        if (providerSettings.issueRefreshTokens()) {
            refreshToken = tokenStore.createRefreshToken(grantType, clientRegistration.getClientId(),
                    resourceOwner.getId(), null, validatedScope, request, validatedClaims);
        }

        final AccessToken accessToken = tokenStore.createAccessToken(grantType, BEARER, null,
                resourceOwner.getId(), clientRegistration.getClientId(), null, validatedScope,
                refreshToken, null, validatedClaims, request);

        if (refreshToken != null) {
            accessToken.addExtraData(REFRESH_TOKEN, refreshToken.getTokenId());
        }

        providerSettings.additionalDataToReturnFromTokenEndpoint(accessToken, request);

        if (validatedScope != null && !validatedScope.isEmpty()) {
            accessToken.addExtraData(SCOPE, Utils.joinScope(validatedScope));
        }

        tokenStore.updateAccessToken(accessToken);

        return accessToken;
    }

    @Inject public  PasswordCredentialsGrantTypeHandler(ClientAuthenticator clientAuthenticator,
            List<PasswordCredentialsRequestValidator> requestValidators,
            ResourceOwnerAuthenticator resourceOwnerAuthenticator,
            OAuth2ProviderSettingsFactory providerSettingsFactory, OAuth2UrisFactory urisFactory,
            TokenStore tokenStore);

}