auth
auth/grant.go
More tests, login redirect bugfix. Add tests for our cookie checking helper and our helper for generating login redirection URIs. Fix a bug where the URL to redirect to was being URL-encoded twice when included in the login redirect URI.
| paddy@26 | 1 package auth |
| paddy@26 | 2 |
| paddy@26 | 3 import ( |
| paddy@29 | 4 "errors" |
| paddy@26 | 5 "time" |
| paddy@26 | 6 |
| paddy@45 | 7 "code.secondbit.org/uuid" |
| paddy@26 | 8 ) |
| paddy@26 | 9 |
| paddy@29 | 10 var ( |
| paddy@57 | 11 // ErrNoGrantStore is returned when a Context tries to act on a grantStore without setting one first. |
| paddy@57 | 12 ErrNoGrantStore = errors.New("no grantStore was specified for the Context") |
| paddy@57 | 13 // ErrGrantNotFound is returned when a Grant is requested but not found in the grantStore. |
| paddy@57 | 14 ErrGrantNotFound = errors.New("grant not found in grantStore") |
| paddy@57 | 15 // ErrGrantAlreadyExists is returned when a Grant is added to a grantStore, but another Grant with the |
| paddy@57 | 16 // same Code already exists in the grantStore. |
| paddy@57 | 17 ErrGrantAlreadyExists = errors.New("grant already exists in grantStore") |
| paddy@29 | 18 ) |
| paddy@29 | 19 |
| paddy@57 | 20 // Grant represents an authorization grant made by a user to a Client, to |
| paddy@57 | 21 // access user data within a defined Scope for a limited amount of time. |
| paddy@26 | 22 type Grant struct { |
| paddy@26 | 23 Code string |
| paddy@26 | 24 Created time.Time |
| paddy@26 | 25 ExpiresIn int32 |
| paddy@26 | 26 ClientID uuid.ID |
| paddy@26 | 27 Scope string |
| paddy@26 | 28 RedirectURI string |
| paddy@26 | 29 State string |
| paddy@69 | 30 ProfileID uuid.ID |
| paddy@26 | 31 } |
| paddy@26 | 32 |
| paddy@57 | 33 type grantStore interface { |
| paddy@57 | 34 getGrant(code string) (Grant, error) |
| paddy@57 | 35 saveGrant(grant Grant) error |
| paddy@57 | 36 deleteGrant(code string) error |
| paddy@26 | 37 } |
| paddy@29 | 38 |
| paddy@57 | 39 func (m *memstore) getGrant(code string) (Grant, error) { |
| paddy@29 | 40 m.grantLock.RLock() |
| paddy@29 | 41 defer m.grantLock.RUnlock() |
| paddy@29 | 42 grant, ok := m.grants[code] |
| paddy@29 | 43 if !ok { |
| paddy@29 | 44 return Grant{}, ErrGrantNotFound |
| paddy@29 | 45 } |
| paddy@29 | 46 return grant, nil |
| paddy@29 | 47 } |
| paddy@29 | 48 |
| paddy@57 | 49 func (m *memstore) saveGrant(grant Grant) error { |
| paddy@29 | 50 m.grantLock.Lock() |
| paddy@29 | 51 defer m.grantLock.Unlock() |
| paddy@29 | 52 _, ok := m.grants[grant.Code] |
| paddy@29 | 53 if ok { |
| paddy@29 | 54 return ErrGrantAlreadyExists |
| paddy@29 | 55 } |
| paddy@29 | 56 m.grants[grant.Code] = grant |
| paddy@29 | 57 return nil |
| paddy@29 | 58 } |
| paddy@29 | 59 |
| paddy@57 | 60 func (m *memstore) deleteGrant(code string) error { |
| paddy@29 | 61 m.grantLock.Lock() |
| paddy@29 | 62 defer m.grantLock.Unlock() |
| paddy@29 | 63 _, ok := m.grants[code] |
| paddy@29 | 64 if !ok { |
| paddy@29 | 65 return ErrGrantNotFound |
| paddy@29 | 66 } |
| paddy@29 | 67 delete(m.grants, code) |
| paddy@29 | 68 return nil |
| paddy@29 | 69 } |