DefaultOAuth2AuthorizationCodeService.java

  1. /*******************************************************************************
  2.  * Copyright 2017 The MIT Internet Trust Consortium
  3.  *
  4.  * Portions copyright 2011-2013 The MITRE Corporation
  5.  *
  6.  * Licensed under the Apache License, Version 2.0 (the "License");
  7.  * you may not use this file except in compliance with the License.
  8.  * You may obtain a copy of the License at
  9.  *
  10.  *   http://www.apache.org/licenses/LICENSE-2.0
  11.  *
  12.  * Unless required by applicable law or agreed to in writing, software
  13.  * distributed under the License is distributed on an "AS IS" BASIS,
  14.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15.  * See the License for the specific language governing permissions and
  16.  * limitations under the License.
  17.  *******************************************************************************/
  18. /**
  19.  *
  20.  */
  21. package org.mitre.oauth2.service.impl;

  22. import java.util.Collection;
  23. import java.util.Date;

  24. import org.mitre.data.AbstractPageOperationTemplate;
  25. import org.mitre.oauth2.model.AuthenticationHolderEntity;
  26. import org.mitre.oauth2.model.AuthorizationCodeEntity;
  27. import org.mitre.oauth2.repository.AuthenticationHolderRepository;
  28. import org.mitre.oauth2.repository.AuthorizationCodeRepository;
  29. import org.slf4j.Logger;
  30. import org.slf4j.LoggerFactory;
  31. import org.springframework.beans.factory.annotation.Autowired;
  32. import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
  33. import org.springframework.security.oauth2.common.util.RandomValueStringGenerator;
  34. import org.springframework.security.oauth2.provider.OAuth2Authentication;
  35. import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
  36. import org.springframework.stereotype.Service;
  37. import org.springframework.transaction.annotation.Transactional;

  38. /**
  39.  * Database-backed, random-value authorization code service implementation.
  40.  *
  41.  * @author aanganes
  42.  *
  43.  */
  44. @Service("defaultOAuth2AuthorizationCodeService")
  45. public class DefaultOAuth2AuthorizationCodeService implements AuthorizationCodeServices {
  46.     // Logger for this class
  47.     private static final Logger logger = LoggerFactory.getLogger(DefaultOAuth2AuthorizationCodeService.class);

  48.     @Autowired
  49.     private AuthorizationCodeRepository repository;

  50.     @Autowired
  51.     private AuthenticationHolderRepository authenticationHolderRepository;

  52.     private int authCodeExpirationSeconds = 60 * 5; // expire in 5 minutes by default

  53.     private RandomValueStringGenerator generator = new RandomValueStringGenerator();

  54.     /**
  55.      * Generate a random authorization code and create an AuthorizationCodeEntity,
  56.      * which will be stored in the repository.
  57.      *
  58.      * @param authentication    the authentication of the current user, to be retrieved when the
  59.      *                          code is consumed
  60.      * @return                  the authorization code
  61.      */
  62.     @Override
  63.     @Transactional(value="defaultTransactionManager")
  64.     public String createAuthorizationCode(OAuth2Authentication authentication) {
  65.         String code = generator.generate();

  66.         // attach the authorization so that we can look it up later
  67.         AuthenticationHolderEntity authHolder = new AuthenticationHolderEntity();
  68.         authHolder.setAuthentication(authentication);
  69.         authHolder = authenticationHolderRepository.save(authHolder);

  70.         // set the auth code to expire
  71.         Date expiration = new Date(System.currentTimeMillis() + (getAuthCodeExpirationSeconds() * 1000L));

  72.         AuthorizationCodeEntity entity = new AuthorizationCodeEntity(code, authHolder, expiration);
  73.         repository.save(entity);

  74.         return code;
  75.     }

  76.     /**
  77.      * Consume a given authorization code.
  78.      * Match the provided string to an AuthorizationCodeEntity. If one is found, return
  79.      * the authentication associated with the code. If one is not found, throw an
  80.      * InvalidGrantException.
  81.      *
  82.      * @param code      the authorization code
  83.      * @return          the authentication that made the original request
  84.      * @throws          InvalidGrantException, if an AuthorizationCodeEntity is not found with the given value
  85.      */
  86.     @Override
  87.     public OAuth2Authentication consumeAuthorizationCode(String code) throws InvalidGrantException {

  88.         AuthorizationCodeEntity result = repository.getByCode(code);

  89.         if (result == null) {
  90.             throw new InvalidGrantException("JpaAuthorizationCodeRepository: no authorization code found for value " + code);
  91.         }

  92.         OAuth2Authentication auth = result.getAuthenticationHolder().getAuthentication();

  93.         repository.remove(result);

  94.         return auth;
  95.     }

  96.     /**
  97.      * Find and remove all expired auth codes.
  98.      */
  99.     @Transactional(value="defaultTransactionManager")
  100.     public void clearExpiredAuthorizationCodes() {

  101.         new AbstractPageOperationTemplate<AuthorizationCodeEntity>("clearExpiredAuthorizationCodes"){
  102.             @Override
  103.             public Collection<AuthorizationCodeEntity> fetchPage() {
  104.                 return repository.getExpiredCodes();
  105.             }

  106.             @Override
  107.             protected void doOperation(AuthorizationCodeEntity item) {
  108.                 repository.remove(item);
  109.             }
  110.         }.execute();
  111.     }

  112.     /**
  113.      * @return the repository
  114.      */
  115.     public AuthorizationCodeRepository getRepository() {
  116.         return repository;
  117.     }

  118.     /**
  119.      * @param repository the repository to set
  120.      */
  121.     public void setRepository(AuthorizationCodeRepository repository) {
  122.         this.repository = repository;
  123.     }

  124.     /**
  125.      * @return the authCodeExpirationSeconds
  126.      */
  127.     public int getAuthCodeExpirationSeconds() {
  128.         return authCodeExpirationSeconds;
  129.     }

  130.     /**
  131.      * @param authCodeExpirationSeconds the authCodeExpirationSeconds to set
  132.      */
  133.     public void setAuthCodeExpirationSeconds(int authCodeExpirationSeconds) {
  134.         this.authCodeExpirationSeconds = authCodeExpirationSeconds;
  135.     }

  136. }