github.com/cozy/cozy-stack@v0.0.0-20240327093429-939e4a21320e/model/permission/claims.go (about)

     1  package permission
     2  
     3  import (
     4  	"time"
     5  
     6  	"github.com/cozy/cozy-stack/pkg/consts"
     7  	"github.com/golang-jwt/jwt/v5"
     8  )
     9  
    10  // Claims is used for JWT used in OAuth2 flow and applications token
    11  type Claims struct {
    12  	jwt.RegisteredClaims
    13  	Scope     string `json:"scope,omitempty"`
    14  	SessionID string `json:"session_id,omitempty"`
    15  	SStamp    string `json:"stamp,omitempty"`
    16  }
    17  
    18  // IssuedAtUTC returns a time.Time struct of the IssuedAt field in UTC
    19  // location.
    20  func (claims *Claims) IssuedAtUTC() time.Time {
    21  	return claims.IssuedAt.Time.UTC()
    22  }
    23  
    24  // AudienceString returns the audience as a string.
    25  func (claims *Claims) AudienceString() string {
    26  	if len(claims.Audience) == 0 {
    27  		return ""
    28  	}
    29  	return claims.Audience[0]
    30  }
    31  
    32  // Expired returns true if a Claim is expired
    33  func (claims *Claims) Expired() bool {
    34  	if len(claims.Audience) != 1 {
    35  		return true
    36  	}
    37  
    38  	var validityDuration time.Duration
    39  	switch claims.Audience[0] {
    40  	case consts.AppAudience:
    41  		if claims.SessionID == "" {
    42  			// an app token with no session association is used for services which
    43  			// should have tokens that have the same properties as the konnector's
    44  			// tokens
    45  			validityDuration = consts.KonnectorTokenValidityDuration
    46  		} else {
    47  			validityDuration = consts.AppTokenValidityDuration
    48  		}
    49  
    50  	case consts.KonnectorAudience:
    51  		validityDuration = consts.KonnectorTokenValidityDuration
    52  
    53  	case consts.CLIAudience:
    54  		validityDuration = consts.CLITokenValidityDuration
    55  
    56  	case consts.AccessTokenAudience:
    57  		validityDuration = consts.AccessTokenValidityDuration
    58  
    59  	// Share, RefreshToken and RegistrationToken never expire
    60  	case consts.ShareAudience, consts.RegistrationTokenAudience, consts.RefreshTokenAudience:
    61  		return false
    62  
    63  	default:
    64  		validityDuration = consts.DefaultValidityDuration
    65  	}
    66  	validUntil := claims.IssuedAtUTC().Add(validityDuration)
    67  	return validUntil.Before(time.Now().UTC())
    68  }
    69  
    70  // BitwardenClaims are used for bitwarden clients. The bitwarden protocol
    71  // expects some additional fields. Also, the subject must be the UserID, and
    72  // the usual subject for Cozy OAuth clients are the id of the OAuth client
    73  // which is not suitable here (the UserID must be the same for all bitwarden
    74  // clients, as it is used to compute the user fingerprint). So, the client ID
    75  // is saved in an additional field, client_id, and we are doing some tricks
    76  // to make the stack accepts those JWT.
    77  type BitwardenClaims struct {
    78  	Claims
    79  	ClientID string `json:"client_id"`
    80  	Name     string `json:"name"`
    81  	Email    string `json:"email"`
    82  	Verified bool   `json:"email_verified"`
    83  	Premium  bool   `json:"premium"`
    84  }