auth

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

72:ade4f4afd898 Go to Latest

auth/token.go

Already pulled client ID out of basic auth. Remove another finished TODO.

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