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