diff options
| author | jwijenbergh <jeroenwijenbergh@protonmail.com> | 2024-02-06 14:44:18 +0100 |
|---|---|---|
| committer | Jeroen Wijenbergh <46386452+jwijenbergh@users.noreply.github.com> | 2024-02-19 14:15:07 +0100 |
| commit | 4d26c8489b09acc98128715e9a2ed67558eb8105 (patch) | |
| tree | 0ed8f4c95c12e501bc1a78c646c707ed6618936b /internal/oauth/token.go | |
| parent | 3fd29f3e1c963196cac69fcbb9d68116f7ea80ec (diff) | |
Util + OAuth: Delete internal OAuth implementation
Preparing to move to github.com/jwijenbergh/eduoauth-go
Diffstat (limited to 'internal/oauth/token.go')
| -rw-r--r-- | internal/oauth/token.go | 162 |
1 files changed, 0 insertions, 162 deletions
diff --git a/internal/oauth/token.go b/internal/oauth/token.go deleted file mode 100644 index 251b689..0000000 --- a/internal/oauth/token.go +++ /dev/null @@ -1,162 +0,0 @@ -package oauth - -import ( - "context" - "fmt" - "sync" - "time" - - "github.com/eduvpn/eduvpn-common/internal/log" - "github.com/eduvpn/eduvpn-common/types/server" - "github.com/go-errors/errors" -) - -// TokenResponse defines the OAuth response from the server that includes the tokens. -type TokenResponse struct { - // Access is the access token returned by the server - Access string `json:"access_token"` - - // Refresh token is the refresh token returned by the server - Refresh string `json:"refresh_token"` - - // Type indicates which type of tokens we have - Type string `json:"token_type"` - - // Expires is the expires time returned by the server - Expires int64 `json:"expires_in"` -} - -// The public type that can be passed to an update function -// It contains our access and refresh tokens with a timestamp -type Token struct { - // Access is the Access token returned by the server - Access string - - // Refresh token is the Refresh token returned by the server - Refresh string - - // ExpiredTimestamp is the Expires field but converted to a Go timestamp - ExpiredTimestamp time.Time -} - -func (t *Token) Public() server.Tokens { - return server.Tokens{ - Access: t.Access, - Refresh: t.Refresh, - Expires: t.ExpiredTimestamp.Unix(), - } -} - -// tokenRefresher is a structure that contains our access and refresh tokens and a timestamp when they expire. -// Additionally, it contains the refresher to get new tokens -type tokenRefresher struct { - Token - // Refresher is the function that refreshes the token - Refresher func(context.Context, string) (*TokenResponse, time.Time, error) -} - -// tokenLock is a wrapper around token that protects it with a lock -type tokenLock struct { - // Protects t - mu sync.Mutex - - // The token fields protected by the lock - // This token struct contains a refresher - t *tokenRefresher -} - -// Access gets the OAuth access token used for contacting the server API -// It returns the access token as a string, possibly obtained fresh using the refresher -// If the token cannot be obtained, an error is returned and the token is an empty string. -func (l *tokenLock) Access(ctx context.Context) (string, error) { - log.Logger.Debugf("Getting access token") - l.mu.Lock() - defer l.mu.Unlock() - - // The tokens are not expired yet - // So they should be valid, re-login not neede - if !l.expired() { - log.Logger.Debugf("Access token is not expired, returning") - return l.t.Access, nil - } - - // Check if refresh is even possible by doing a simple check if the refresh token is empty - // This is not needed but reduces API calls to the server - if l.t.Refresh == "" { - log.Logger.Debugf("Refresh token is empty, returning error") - return "", errors.Wrap(&TokensInvalidError{Cause: "no refresh token is present"}, 0) - } - - // Otherwise refresh and then later return the access token if we are successful - tr, s, err := l.t.Refresher(ctx, l.t.Refresh) - if err != nil { - log.Logger.Debugf("Got a refresh token error: %v", err) - // We have failed to ensure the tokens due to refresh not working - return "", errors.Wrap( - &TokensInvalidError{Cause: fmt.Sprintf("tokens failed refresh with error: %v", err)}, 0) - } - if tr == nil { - log.Logger.Debugf("No token response after refreshing") - return "", errors.New("No token response after refreshing") - } - // store the previous refresh token - pr := l.t.Refresh - // get the response as a non-pointer - r := *tr - e := s.Add(time.Second * time.Duration(r.Expires)) - t := Token{Access: r.Access, Refresh: r.Refresh, ExpiredTimestamp: e} - l.updateInternal(t) - // set the previous refresh token if the new one is empty - // This is for 2.x servers - if l.t.Refresh == "" { - log.Logger.Debugf("The previous refresh token is set as the response had no refresh token") - l.t.Refresh = pr - } - return l.t.Access, nil -} - -// UpdateResponse updates the structure using the server response and locks -func (l *tokenLock) UpdateResponse(r TokenResponse, s time.Time) { - l.mu.Lock() - e := s.Add(time.Second * time.Duration(r.Expires)) - t := Token{Access: r.Access, Refresh: r.Refresh, ExpiredTimestamp: e} - l.updateInternal(t) - l.mu.Unlock() -} - -// updateInternal updates the token structure internally but does not lock -func (l *tokenLock) updateInternal(r Token) { - l.t.Access = r.Access - l.t.Refresh = r.Refresh - l.t.ExpiredTimestamp = r.ExpiredTimestamp -} - -// Update updates the token structure using the internal function but locks -func (l *tokenLock) Update(r Token) { - l.mu.Lock() - l.updateInternal(r) - l.mu.Unlock() -} - -// Get gets the tokens into a public struct -func (l *tokenLock) Get() Token { - // TODO: Check nil? - l.mu.Lock() - defer l.mu.Unlock() - return l.t.Token -} - -// SetExpired overrides the timestamp to the current time -// This marks the tokens as expired -func (l *tokenLock) SetExpired() { - l.mu.Lock() - l.t.ExpiredTimestamp = time.Now() - l.mu.Unlock() -} - -// expired checks if the access token is expired. -// This is only called internally and thus does not lock -func (l *tokenLock) expired() bool { - now := time.Now() - return !now.Before(l.t.ExpiredTimestamp) -} |
