auth

Paddy 2014-12-14 Parent:9c50b2e2e03b Child:c03b5eb3179e

102:267483f168b5 Go to Latest

auth/authcode.go

Require config.Init in Context, add comment. Add comment to config.Init explaining what it is, to make golint happy. Create an ErrConfigNotInitialized error to use when a Config object is used to create a Context before it is initialized. Check for Config initialization in NewContext and throw ErrConfigNotInitialized if the Config hasn't been initialized.

History
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 Invalidate: authCodeGrantInvalidate,
16 IssuesRefresh: true,
17 ReturnToken: RenderJSONToken,
18 })
19 }
21 var (
22 // ErrNoAuthorizationCodeStore is returned when a Context tries to act on a authorizationCodeStore without setting one first.
23 ErrNoAuthorizationCodeStore = errors.New("no authorizationCodeStore was specified for the Context")
24 // ErrAuthorizationCodeNotFound is returned when an AuthorizationCode is requested but not found in the authorizationCodeStore.
25 ErrAuthorizationCodeNotFound = errors.New("authorization code not found in authorizationCodeStore")
26 // ErrAuthorizationCodeAlreadyExists is returned when an AuthorizationCode is added to a authorizationCodeStore, but another AuthorizationCode with the
27 // same Code already exists in the authorizationCodeStore.
28 ErrAuthorizationCodeAlreadyExists = errors.New("authorization code already exists in authorizationCodeStore")
29 )
31 // AuthorizationCode represents an authorization grant made by a user to a Client, to
32 // access user data within a defined Scope for a limited amount of time.
33 type AuthorizationCode struct {
34 Code string
35 Created time.Time
36 ExpiresIn int32
37 ClientID uuid.ID
38 Scope string
39 RedirectURI string
40 State string
41 ProfileID uuid.ID
42 Used bool
43 }
45 type authorizationCodeStore interface {
46 getAuthorizationCode(code string) (AuthorizationCode, error)
47 saveAuthorizationCode(authCode AuthorizationCode) error
48 deleteAuthorizationCode(code string) error
49 useAuthorizationCode(code string) error
50 }
52 func (m *memstore) getAuthorizationCode(code string) (AuthorizationCode, error) {
53 m.authCodeLock.RLock()
54 defer m.authCodeLock.RUnlock()
55 authCode, ok := m.authCodes[code]
56 if !ok {
57 return AuthorizationCode{}, ErrAuthorizationCodeNotFound
58 }
59 return authCode, nil
60 }
62 func (m *memstore) saveAuthorizationCode(authCode AuthorizationCode) error {
63 m.authCodeLock.Lock()
64 defer m.authCodeLock.Unlock()
65 _, ok := m.authCodes[authCode.Code]
66 if ok {
67 return ErrAuthorizationCodeAlreadyExists
68 }
69 m.authCodes[authCode.Code] = authCode
70 return nil
71 }
73 func (m *memstore) deleteAuthorizationCode(code string) error {
74 m.authCodeLock.Lock()
75 defer m.authCodeLock.Unlock()
76 _, ok := m.authCodes[code]
77 if !ok {
78 return ErrAuthorizationCodeNotFound
79 }
80 delete(m.authCodes, code)
81 return nil
82 }
84 func (m *memstore) useAuthorizationCode(code string) error {
85 m.authCodeLock.Lock()
86 defer m.authCodeLock.Unlock()
87 a, ok := m.authCodes[code]
88 if !ok {
89 return ErrAuthorizationCodeNotFound
90 }
91 a.Used = true
92 m.authCodes[code] = a
93 return nil
94 }
96 func authCodeGrantValidate(w http.ResponseWriter, r *http.Request, context Context) (scope string, profileID uuid.ID, valid bool) {
97 enc := json.NewEncoder(w)
98 code := r.PostFormValue("code")
99 if code == "" {
100 w.WriteHeader(http.StatusBadRequest)
101 renderJSONError(enc, "invalid_request")
102 return
103 }
104 clientID, success := verifyClient(w, r, true, context)
105 if !success {
106 return
107 }
108 authCode, err := context.GetAuthorizationCode(code)
109 if err != nil {
110 if err == ErrAuthorizationCodeNotFound {
111 w.WriteHeader(http.StatusBadRequest)
112 renderJSONError(enc, "invalid_grant")
113 return
114 }
115 w.WriteHeader(http.StatusInternalServerError)
116 renderJSONError(enc, "server_error")
117 return
118 }
119 redirectURI := r.PostFormValue("redirect_uri")
120 if authCode.RedirectURI != redirectURI {
121 w.WriteHeader(http.StatusBadRequest)
122 renderJSONError(enc, "invalid_grant")
123 return
124 }
125 if !authCode.ClientID.Equal(clientID) {
126 w.WriteHeader(http.StatusBadRequest)
127 renderJSONError(enc, "invalid_grant")
128 return
129 }
130 return authCode.Scope, authCode.ProfileID, true
131 }
133 func authCodeGrantInvalidate(r *http.Request, context Context) error {
134 code := r.PostFormValue("code")
135 if code == "" {
136 return ErrAuthorizationCodeNotFound
137 }
138 return context.UseAuthorizationCode(code)
139 }