auth

Paddy 2014-11-11 Parent:42bc3e44f4fe Child:61a802849b51

71:c8b0208c9e5d Go to Latest

auth/token.go

Remove extraneous TODOs. One TODO shouldn't actually be done. Another is already done. Remove both.

History
paddy@28 1 package auth
paddy@28 2
paddy@28 3 import (
paddy@28 4 "errors"
paddy@28 5 "time"
paddy@28 6
paddy@45 7 "code.secondbit.org/uuid"
paddy@28 8 )
paddy@28 9
paddy@69 10 const (
paddy@69 11 defaultTokenExpiration = 3600 // one hour
paddy@69 12 )
paddy@69 13
paddy@28 14 var (
paddy@57 15 // ErrNoTokenStore is returned when a Context tries to act on a tokenStore without setting one first.
paddy@57 16 ErrNoTokenStore = errors.New("no tokenStore was specified for the Context")
paddy@57 17 // ErrTokenNotFound is returned when a Token is requested but not found in a tokenStore.
paddy@57 18 ErrTokenNotFound = errors.New("token not found in tokenStore")
paddy@57 19 // ErrTokenAlreadyExists is returned when a Token is added to a tokenStore, but another Token with
paddy@57 20 // the same AccessToken property already exists in the tokenStore.
paddy@57 21 ErrTokenAlreadyExists = errors.New("token already exists in tokenStore")
paddy@28 22 )
paddy@28 23
paddy@57 24 // Token represents an access and/or refresh token that the Client can use to access user data
paddy@57 25 // or obtain a new access token.
paddy@28 26 type Token struct {
paddy@28 27 AccessToken string
paddy@28 28 RefreshToken string
paddy@28 29 Created time.Time
paddy@28 30 ExpiresIn int32
paddy@28 31 TokenType string
paddy@28 32 Scope string
paddy@28 33 ProfileID uuid.ID
paddy@28 34 }
paddy@28 35
paddy@57 36 type tokenStore interface {
paddy@57 37 getToken(token string, refresh bool) (Token, error)
paddy@57 38 saveToken(token Token) error
paddy@57 39 removeToken(token string) error
paddy@57 40 getTokensByProfileID(profileID uuid.ID, num, offset int) ([]Token, error)
paddy@28 41 }
paddy@28 42
paddy@57 43 func (m *memstore) getToken(token string, refresh bool) (Token, error) {
paddy@28 44 if refresh {
paddy@28 45 t, err := m.lookupTokenByRefresh(token)
paddy@28 46 if err != nil {
paddy@28 47 return Token{}, err
paddy@28 48 }
paddy@28 49 token = t
paddy@28 50 }
paddy@28 51 m.tokenLock.RLock()
paddy@28 52 defer m.tokenLock.RUnlock()
paddy@28 53 result, ok := m.tokens[token]
paddy@28 54 if !ok {
paddy@28 55 return Token{}, ErrTokenNotFound
paddy@28 56 }
paddy@28 57 return result, nil
paddy@28 58 }
paddy@28 59
paddy@57 60 func (m *memstore) saveToken(token Token) error {
paddy@28 61 m.tokenLock.Lock()
paddy@28 62 defer m.tokenLock.Unlock()
paddy@28 63 _, ok := m.tokens[token.AccessToken]
paddy@28 64 if ok {
paddy@28 65 return ErrTokenAlreadyExists
paddy@28 66 }
paddy@28 67 m.tokens[token.AccessToken] = token
paddy@28 68 if token.RefreshToken != "" {
paddy@28 69 m.refreshTokenLookup[token.RefreshToken] = token.AccessToken
paddy@28 70 }
paddy@28 71 if _, ok = m.profileTokenLookup[token.ProfileID.String()]; ok {
paddy@28 72 m.profileTokenLookup[token.ProfileID.String()] = append(m.profileTokenLookup[token.ProfileID.String()], token.AccessToken)
paddy@28 73 } else {
paddy@28 74 m.profileTokenLookup[token.ProfileID.String()] = []string{token.AccessToken}
paddy@28 75 }
paddy@28 76 return nil
paddy@28 77 }
paddy@28 78
paddy@57 79 func (m *memstore) removeToken(token string) error {
paddy@28 80 m.tokenLock.Lock()
paddy@28 81 defer m.tokenLock.Unlock()
paddy@28 82 t, ok := m.tokens[token]
paddy@28 83 if !ok {
paddy@28 84 return ErrTokenNotFound
paddy@28 85 }
paddy@28 86 delete(m.tokens, token)
paddy@28 87 if t.RefreshToken != "" {
paddy@28 88 delete(m.refreshTokenLookup, t.RefreshToken)
paddy@28 89 }
paddy@28 90 pos := -1
paddy@28 91 for p, item := range m.profileTokenLookup[t.ProfileID.String()] {
paddy@28 92 if item == token {
paddy@28 93 pos = p
paddy@28 94 break
paddy@28 95 }
paddy@28 96 }
paddy@28 97 if pos >= 0 {
paddy@28 98 m.profileTokenLookup[t.ProfileID.String()] = append(m.profileTokenLookup[t.ProfileID.String()][:pos], m.profileTokenLookup[t.ProfileID.String()][pos+1:]...)
paddy@28 99 }
paddy@28 100 return nil
paddy@28 101 }
paddy@28 102
paddy@57 103 func (m *memstore) getTokensByProfileID(profileID uuid.ID, num, offset int) ([]Token, error) {
paddy@28 104 ids, err := m.lookupTokensByProfileID(profileID.String())
paddy@28 105 if err != nil {
paddy@28 106 return []Token{}, err
paddy@28 107 }
paddy@28 108 if len(ids) > num+offset {
paddy@28 109 ids = ids[offset : num+offset]
paddy@28 110 } else if len(ids) > offset {
paddy@28 111 ids = ids[offset:]
paddy@28 112 } else {
paddy@28 113 return []Token{}, nil
paddy@28 114 }
paddy@28 115 tokens := []Token{}
paddy@28 116 for _, id := range ids {
paddy@57 117 token, err := m.getToken(id, false)
paddy@28 118 if err != nil {
paddy@28 119 return []Token{}, err
paddy@28 120 }
paddy@28 121 tokens = append(tokens, token)
paddy@28 122 }
paddy@28 123 return tokens, nil
paddy@28 124 }