auth

Paddy 2014-12-07 Parent:1dc4e152e3b0

86:7f64033806bb Go to Latest

auth/grant.go

Document RenderJSONToken. Document the RenderJSONToken to satisfy golint.

History
paddy@26 1 package auth
paddy@26 2
paddy@26 3 import (
paddy@84 4 "encoding/json"
paddy@29 5 "errors"
paddy@84 6 "net/http"
paddy@26 7 "time"
paddy@26 8
paddy@45 9 "code.secondbit.org/uuid"
paddy@26 10 )
paddy@26 11
paddy@84 12 func init() {
paddy@84 13 RegisterGrantType("authorization_code", GrantType{
paddy@84 14 Validate: authCodeGrantValidate,
paddy@84 15 IssuesRefresh: true,
paddy@85 16 ReturnToken: RenderJSONToken,
paddy@84 17 })
paddy@84 18 }
paddy@84 19
paddy@29 20 var (
paddy@57 21 // ErrNoGrantStore is returned when a Context tries to act on a grantStore without setting one first.
paddy@57 22 ErrNoGrantStore = errors.New("no grantStore was specified for the Context")
paddy@57 23 // ErrGrantNotFound is returned when a Grant is requested but not found in the grantStore.
paddy@57 24 ErrGrantNotFound = errors.New("grant not found in grantStore")
paddy@57 25 // ErrGrantAlreadyExists is returned when a Grant is added to a grantStore, but another Grant with the
paddy@57 26 // same Code already exists in the grantStore.
paddy@57 27 ErrGrantAlreadyExists = errors.New("grant already exists in grantStore")
paddy@29 28 )
paddy@29 29
paddy@57 30 // Grant represents an authorization grant made by a user to a Client, to
paddy@57 31 // access user data within a defined Scope for a limited amount of time.
paddy@26 32 type Grant struct {
paddy@26 33 Code string
paddy@26 34 Created time.Time
paddy@26 35 ExpiresIn int32
paddy@26 36 ClientID uuid.ID
paddy@26 37 Scope string
paddy@26 38 RedirectURI string
paddy@26 39 State string
paddy@69 40 ProfileID uuid.ID
paddy@26 41 }
paddy@26 42
paddy@57 43 type grantStore interface {
paddy@57 44 getGrant(code string) (Grant, error)
paddy@57 45 saveGrant(grant Grant) error
paddy@57 46 deleteGrant(code string) error
paddy@26 47 }
paddy@29 48
paddy@57 49 func (m *memstore) getGrant(code string) (Grant, error) {
paddy@29 50 m.grantLock.RLock()
paddy@29 51 defer m.grantLock.RUnlock()
paddy@29 52 grant, ok := m.grants[code]
paddy@29 53 if !ok {
paddy@29 54 return Grant{}, ErrGrantNotFound
paddy@29 55 }
paddy@29 56 return grant, nil
paddy@29 57 }
paddy@29 58
paddy@57 59 func (m *memstore) saveGrant(grant Grant) error {
paddy@29 60 m.grantLock.Lock()
paddy@29 61 defer m.grantLock.Unlock()
paddy@29 62 _, ok := m.grants[grant.Code]
paddy@29 63 if ok {
paddy@29 64 return ErrGrantAlreadyExists
paddy@29 65 }
paddy@29 66 m.grants[grant.Code] = grant
paddy@29 67 return nil
paddy@29 68 }
paddy@29 69
paddy@57 70 func (m *memstore) deleteGrant(code string) error {
paddy@29 71 m.grantLock.Lock()
paddy@29 72 defer m.grantLock.Unlock()
paddy@29 73 _, ok := m.grants[code]
paddy@29 74 if !ok {
paddy@29 75 return ErrGrantNotFound
paddy@29 76 }
paddy@29 77 delete(m.grants, code)
paddy@29 78 return nil
paddy@29 79 }
paddy@84 80
paddy@84 81 func authCodeGrantValidate(w http.ResponseWriter, r *http.Request, context Context) (scope string, profileID uuid.ID, valid bool) {
paddy@84 82 enc := json.NewEncoder(w)
paddy@84 83 code := r.PostFormValue("code")
paddy@84 84 if code == "" {
paddy@84 85 w.WriteHeader(http.StatusBadRequest)
paddy@84 86 renderJSONError(enc, "invalid_request")
paddy@84 87 return
paddy@84 88 }
paddy@85 89 clientID, success := verifyClient(w, r, true, context)
paddy@85 90 if !success {
paddy@84 91 return
paddy@84 92 }
paddy@84 93 grant, err := context.GetGrant(code)
paddy@84 94 if err != nil {
paddy@84 95 if err == ErrGrantNotFound {
paddy@84 96 w.WriteHeader(http.StatusBadRequest)
paddy@84 97 renderJSONError(enc, "invalid_grant")
paddy@84 98 return
paddy@84 99 }
paddy@84 100 w.WriteHeader(http.StatusInternalServerError)
paddy@84 101 renderJSONError(enc, "server_error")
paddy@84 102 return
paddy@84 103 }
paddy@85 104 redirectURI := r.PostFormValue("redirect_uri")
paddy@84 105 if grant.RedirectURI != redirectURI {
paddy@84 106 w.WriteHeader(http.StatusBadRequest)
paddy@84 107 renderJSONError(enc, "invalid_grant")
paddy@84 108 return
paddy@84 109 }
paddy@84 110 if !grant.ClientID.Equal(clientID) {
paddy@84 111 w.WriteHeader(http.StatusBadRequest)
paddy@84 112 renderJSONError(enc, "invalid_grant")
paddy@84 113 return
paddy@84 114 }
paddy@84 115 return grant.Scope, grant.ProfileID, true
paddy@84 116 }