github.com/RichardKnop/go-oauth2-server@v1.0.5-0.20201019163316-d02a401490d0/oauth/refresh_token.go (about)

     1  package oauth
     2  
     3  import (
     4  	"errors"
     5  	"time"
     6  
     7  	"github.com/RichardKnop/go-oauth2-server/models"
     8  	"github.com/RichardKnop/go-oauth2-server/util"
     9  )
    10  
    11  var (
    12  	// ErrRefreshTokenNotFound ...
    13  	ErrRefreshTokenNotFound = errors.New("Refresh token not found")
    14  	// ErrRefreshTokenExpired ...
    15  	ErrRefreshTokenExpired = errors.New("Refresh token expired")
    16  	// ErrRequestedScopeCannotBeGreater ...
    17  	ErrRequestedScopeCannotBeGreater = errors.New("Requested scope cannot be greater")
    18  )
    19  
    20  // GetOrCreateRefreshToken retrieves an existing refresh token, if expired,
    21  // the token gets deleted and new refresh token is created
    22  func (s *Service) GetOrCreateRefreshToken(client *models.OauthClient, user *models.OauthUser, expiresIn int, scope string) (*models.OauthRefreshToken, error) {
    23  	// Try to fetch an existing refresh token first
    24  	refreshToken := new(models.OauthRefreshToken)
    25  	query := models.OauthRefreshTokenPreload(s.db).Where("client_id = ?", client.ID)
    26  	if user != nil && len([]rune(user.ID)) > 0 {
    27  		query = query.Where("user_id = ?", user.ID)
    28  	} else {
    29  		query = query.Where("user_id IS NULL")
    30  	}
    31  	found := !query.First(refreshToken).RecordNotFound()
    32  
    33  	// Check if the token is expired, if found
    34  	var expired bool
    35  	if found {
    36  		expired = time.Now().UTC().After(refreshToken.ExpiresAt)
    37  	}
    38  
    39  	// If the refresh token has expired, delete it
    40  	if expired {
    41  		s.db.Unscoped().Delete(refreshToken)
    42  	}
    43  
    44  	// Create a new refresh token if it expired or was not found
    45  	if expired || !found {
    46  		refreshToken = models.NewOauthRefreshToken(client, user, expiresIn, scope)
    47  		if err := s.db.Create(refreshToken).Error; err != nil {
    48  			return nil, err
    49  		}
    50  		refreshToken.Client = client
    51  		refreshToken.User = user
    52  	}
    53  
    54  	return refreshToken, nil
    55  }
    56  
    57  // GetValidRefreshToken returns a valid non expired refresh token
    58  func (s *Service) GetValidRefreshToken(token string, client *models.OauthClient) (*models.OauthRefreshToken, error) {
    59  	// Fetch the refresh token from the database
    60  	refreshToken := new(models.OauthRefreshToken)
    61  	notFound := models.OauthRefreshTokenPreload(s.db).Where("client_id = ?", client.ID).
    62  		Where("token = ?", token).First(refreshToken).RecordNotFound()
    63  
    64  	// Not found
    65  	if notFound {
    66  		return nil, ErrRefreshTokenNotFound
    67  	}
    68  
    69  	// Check the refresh token hasn't expired
    70  	if time.Now().UTC().After(refreshToken.ExpiresAt) {
    71  		return nil, ErrRefreshTokenExpired
    72  	}
    73  
    74  	return refreshToken, nil
    75  }
    76  
    77  // getRefreshTokenScope returns scope for a new refresh token
    78  func (s *Service) getRefreshTokenScope(refreshToken *models.OauthRefreshToken, requestedScope string) (string, error) {
    79  	var (
    80  		scope = refreshToken.Scope // default to the scope originally granted by the resource owner
    81  		err   error
    82  	)
    83  
    84  	// If the scope is specified in the request, get the scope string
    85  	if requestedScope != "" {
    86  		scope, err = s.GetScope(requestedScope)
    87  		if err != nil {
    88  			return "", err
    89  		}
    90  	}
    91  
    92  	// Requested scope CANNOT include any scope not originally granted
    93  	if !util.SpaceDelimitedStringNotGreater(scope, refreshToken.Scope) {
    94  		return "", ErrRequestedScopeCannotBeGreater
    95  	}
    96  
    97  	return scope, nil
    98  }