auth
87:1fb166575e69 Browse Files
Rename Grant to AuthorizationCode. God bless gofmt. Rename all our instances of Grant to AuthorizationCode (including related variables and types, like grantStore and ErrGrantNotFound, plus all our comments and error strings. Whew.) to better reflect that it is only a single type of grant that could be accepted by the server.
authcode.go authcode_test.go context.go grant.go grant_test.go memstore.go oauth2.go oauth2_test.go
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/authcode.go Sun Dec 07 03:40:25 2014 -0500 1.3 @@ -0,0 +1,116 @@ 1.4 +package auth 1.5 + 1.6 +import ( 1.7 + "encoding/json" 1.8 + "errors" 1.9 + "net/http" 1.10 + "time" 1.11 + 1.12 + "code.secondbit.org/uuid" 1.13 +) 1.14 + 1.15 +func init() { 1.16 + RegisterGrantType("authorization_code", GrantType{ 1.17 + Validate: authCodeGrantValidate, 1.18 + IssuesRefresh: true, 1.19 + ReturnToken: RenderJSONToken, 1.20 + }) 1.21 +} 1.22 + 1.23 +var ( 1.24 + // ErrNoAuthorizationCodeStore is returned when a Context tries to act on a authorizationCodeStore without setting one first. 1.25 + ErrNoAuthorizationCodeStore = errors.New("no authorizationCodeStore was specified for the Context") 1.26 + // ErrAuthorizationCodeNotFound is returned when an AuthorizationCode is requested but not found in the authorizationCodeStore. 1.27 + ErrAuthorizationCodeNotFound = errors.New("authorization code not found in authorizationCodeStore") 1.28 + // ErrAuthorizationCodeAlreadyExists is returned when an AuthorizationCode is added to a authorizationCodeStore, but another AuthorizationCode with the 1.29 + // same Code already exists in the authorizationCodeStore. 1.30 + ErrAuthorizationCodeAlreadyExists = errors.New("authorization code already exists in authorizationCodeStore") 1.31 +) 1.32 + 1.33 +// AuthorizationCode represents an authorization grant made by a user to a Client, to 1.34 +// access user data within a defined Scope for a limited amount of time. 1.35 +type AuthorizationCode struct { 1.36 + Code string 1.37 + Created time.Time 1.38 + ExpiresIn int32 1.39 + ClientID uuid.ID 1.40 + Scope string 1.41 + RedirectURI string 1.42 + State string 1.43 + ProfileID uuid.ID 1.44 +} 1.45 + 1.46 +type authorizationCodeStore interface { 1.47 + getAuthorizationCode(code string) (AuthorizationCode, error) 1.48 + saveAuthorizationCode(authCode AuthorizationCode) error 1.49 + deleteAuthorizationCode(code string) error 1.50 +} 1.51 + 1.52 +func (m *memstore) getAuthorizationCode(code string) (AuthorizationCode, error) { 1.53 + m.authCodeLock.RLock() 1.54 + defer m.authCodeLock.RUnlock() 1.55 + authCode, ok := m.authCodes[code] 1.56 + if !ok { 1.57 + return AuthorizationCode{}, ErrAuthorizationCodeNotFound 1.58 + } 1.59 + return authCode, nil 1.60 +} 1.61 + 1.62 +func (m *memstore) saveAuthorizationCode(authCode AuthorizationCode) error { 1.63 + m.authCodeLock.Lock() 1.64 + defer m.authCodeLock.Unlock() 1.65 + _, ok := m.authCodes[authCode.Code] 1.66 + if ok { 1.67 + return ErrAuthorizationCodeAlreadyExists 1.68 + } 1.69 + m.authCodes[authCode.Code] = authCode 1.70 + return nil 1.71 +} 1.72 + 1.73 +func (m *memstore) deleteAuthorizationCode(code string) error { 1.74 + m.authCodeLock.Lock() 1.75 + defer m.authCodeLock.Unlock() 1.76 + _, ok := m.authCodes[code] 1.77 + if !ok { 1.78 + return ErrAuthorizationCodeNotFound 1.79 + } 1.80 + delete(m.authCodes, code) 1.81 + return nil 1.82 +} 1.83 + 1.84 +func authCodeGrantValidate(w http.ResponseWriter, r *http.Request, context Context) (scope string, profileID uuid.ID, valid bool) { 1.85 + enc := json.NewEncoder(w) 1.86 + code := r.PostFormValue("code") 1.87 + if code == "" { 1.88 + w.WriteHeader(http.StatusBadRequest) 1.89 + renderJSONError(enc, "invalid_request") 1.90 + return 1.91 + } 1.92 + clientID, success := verifyClient(w, r, true, context) 1.93 + if !success { 1.94 + return 1.95 + } 1.96 + authCode, err := context.GetAuthorizationCode(code) 1.97 + if err != nil { 1.98 + if err == ErrAuthorizationCodeNotFound { 1.99 + w.WriteHeader(http.StatusBadRequest) 1.100 + renderJSONError(enc, "invalid_grant") 1.101 + return 1.102 + } 1.103 + w.WriteHeader(http.StatusInternalServerError) 1.104 + renderJSONError(enc, "server_error") 1.105 + return 1.106 + } 1.107 + redirectURI := r.PostFormValue("redirect_uri") 1.108 + if authCode.RedirectURI != redirectURI { 1.109 + w.WriteHeader(http.StatusBadRequest) 1.110 + renderJSONError(enc, "invalid_grant") 1.111 + return 1.112 + } 1.113 + if !authCode.ClientID.Equal(clientID) { 1.114 + w.WriteHeader(http.StatusBadRequest) 1.115 + renderJSONError(enc, "invalid_grant") 1.116 + return 1.117 + } 1.118 + return authCode.Scope, authCode.ProfileID, true 1.119 +}
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/authcode_test.go Sun Dec 07 03:40:25 2014 -0500 2.3 @@ -0,0 +1,78 @@ 2.4 +package auth 2.5 + 2.6 +import ( 2.7 + "testing" 2.8 + "time" 2.9 + 2.10 + "code.secondbit.org/uuid" 2.11 +) 2.12 + 2.13 +var authCodeStores = []authorizationCodeStore{NewMemstore()} 2.14 + 2.15 +func compareAuthorizationCodes(authCode1, authCode2 AuthorizationCode) (success bool, field string, authCode1val, authCode2val interface{}) { 2.16 + if authCode1.Code != authCode2.Code { 2.17 + return false, "code", authCode1.Code, authCode2.Code 2.18 + } 2.19 + if !authCode1.Created.Equal(authCode2.Created) { 2.20 + return false, "created", authCode1.Created, authCode2.Created 2.21 + } 2.22 + if authCode1.ExpiresIn != authCode2.ExpiresIn { 2.23 + return false, "expires in", authCode1.ExpiresIn, authCode2.ExpiresIn 2.24 + } 2.25 + if !authCode1.ClientID.Equal(authCode2.ClientID) { 2.26 + return false, "client ID", authCode1.ClientID, authCode2.ClientID 2.27 + } 2.28 + if authCode1.Scope != authCode2.Scope { 2.29 + return false, "scope", authCode1.Scope, authCode2.Scope 2.30 + } 2.31 + if authCode1.RedirectURI != authCode2.RedirectURI { 2.32 + return false, "redirect URI", authCode1.RedirectURI, authCode2.RedirectURI 2.33 + } 2.34 + if authCode1.State != authCode2.State { 2.35 + return false, "state", authCode1.State, authCode2.State 2.36 + } 2.37 + return true, "", nil, nil 2.38 +} 2.39 + 2.40 +func TestAuthorizationCodeStoreSuccess(t *testing.T) { 2.41 + t.Parallel() 2.42 + authCode := AuthorizationCode{ 2.43 + Code: "code", 2.44 + Created: time.Now(), 2.45 + ExpiresIn: 180, 2.46 + ClientID: uuid.NewID(), 2.47 + Scope: "scope", 2.48 + RedirectURI: "redirectURI", 2.49 + State: "state", 2.50 + } 2.51 + for _, store := range authCodeStores { 2.52 + err := store.saveAuthorizationCode(authCode) 2.53 + if err != nil { 2.54 + t.Errorf("Error saving auth code to %T: %s", store, err) 2.55 + } 2.56 + err = store.saveAuthorizationCode(authCode) 2.57 + if err != ErrAuthorizationCodeAlreadyExists { 2.58 + t.Errorf("Expected ErrAuthorizationCodeAlreadyExists from %T, got %+v", store, err) 2.59 + } 2.60 + retrieved, err := store.getAuthorizationCode(authCode.Code) 2.61 + if err != nil { 2.62 + t.Errorf("Error retrieving auth code from %T: %s", store, err) 2.63 + } 2.64 + match, field, expectation, result := compareAuthorizationCodes(authCode, retrieved) 2.65 + if !match { 2.66 + t.Errorf("Expected `%v` in the `%s` field of auth code retrieved from %T, got `%v`", expectation, field, store, result) 2.67 + } 2.68 + err = store.deleteAuthorizationCode(authCode.Code) 2.69 + if err != nil { 2.70 + t.Errorf("Error removing auth code from %T: %s", store, err) 2.71 + } 2.72 + retrieved, err = store.getAuthorizationCode(authCode.Code) 2.73 + if err != ErrAuthorizationCodeNotFound { 2.74 + t.Errorf("Expected ErrAuthorizationCodeNotFound from %T, got %+v and %+v", store, retrieved, err) 2.75 + } 2.76 + err = store.deleteAuthorizationCode(authCode.Code) 2.77 + if err != ErrAuthorizationCodeNotFound { 2.78 + t.Errorf("Expected ErrAuthorizationCodeNotFound from %T, got %+v", store, err) 2.79 + } 2.80 + } 2.81 +}
3.1 --- a/context.go Sun Dec 07 02:54:42 2014 -0500 3.2 +++ b/context.go Sun Dec 07 03:40:25 2014 -0500 3.3 @@ -14,13 +14,13 @@ 3.4 // be used as the main point of interaction for the data storage 3.5 // layer. 3.6 type Context struct { 3.7 - template *template.Template 3.8 - loginURI *url.URL 3.9 - clients clientStore 3.10 - grants grantStore 3.11 - profiles profileStore 3.12 - tokens tokenStore 3.13 - sessions sessionStore 3.14 + template *template.Template 3.15 + loginURI *url.URL 3.16 + clients clientStore 3.17 + authCodes authorizationCodeStore 3.18 + profiles profileStore 3.19 + tokens tokenStore 3.20 + sessions sessionStore 3.21 } 3.22 3.23 // Render uses the HTML templates associated with the Context to render the 3.24 @@ -129,30 +129,30 @@ 3.25 return c.clients.countEndpoints(client) 3.26 } 3.27 3.28 -// GetGrant returns the Grant specified by the provided code from the grantStore associated with the 3.29 +// GetAuthorizationCode returns the AuthorizationCode specified by the provided code from the authorizationCodeStore associated with the 3.30 // Context. 3.31 -func (c Context) GetGrant(code string) (Grant, error) { 3.32 - if c.grants == nil { 3.33 - return Grant{}, ErrNoGrantStore 3.34 +func (c Context) GetAuthorizationCode(code string) (AuthorizationCode, error) { 3.35 + if c.authCodes == nil { 3.36 + return AuthorizationCode{}, ErrNoAuthorizationCodeStore 3.37 } 3.38 - return c.grants.getGrant(code) 3.39 + return c.authCodes.getAuthorizationCode(code) 3.40 } 3.41 3.42 -// SaveGrant stores the passed Grant in the grantStore associated with the Context. 3.43 -func (c Context) SaveGrant(grant Grant) error { 3.44 - if c.grants == nil { 3.45 - return ErrNoGrantStore 3.46 +// SaveAuthorizationCode stores the passed AuthorizationCode in the authorizationCodeStore associated with the Context. 3.47 +func (c Context) SaveAuthorizationCode(authCode AuthorizationCode) error { 3.48 + if c.authCodes == nil { 3.49 + return ErrNoAuthorizationCodeStore 3.50 } 3.51 - return c.grants.saveGrant(grant) 3.52 + return c.authCodes.saveAuthorizationCode(authCode) 3.53 } 3.54 3.55 -// DeleteGrant removes the Grant specified by the provided code from the grantStore associated with 3.56 +// DeleteAuthorizationCode removes the AuthorizationCode specified by the provided code from the authorizationCodeStore associated with 3.57 // the Context. 3.58 -func (c Context) DeleteGrant(code string) error { 3.59 - if c.grants == nil { 3.60 - return ErrNoGrantStore 3.61 +func (c Context) DeleteAuthorizationCode(code string) error { 3.62 + if c.authCodes == nil { 3.63 + return ErrNoAuthorizationCodeStore 3.64 } 3.65 - return c.grants.deleteGrant(code) 3.66 + return c.authCodes.deleteAuthorizationCode(code) 3.67 } 3.68 3.69 // GetProfileByID returns the Profile specified by the provided ID from the profileStore associated with
4.1 --- a/grant.go Sun Dec 07 02:54:42 2014 -0500 4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 4.3 @@ -1,116 +0,0 @@ 4.4 -package auth 4.5 - 4.6 -import ( 4.7 - "encoding/json" 4.8 - "errors" 4.9 - "net/http" 4.10 - "time" 4.11 - 4.12 - "code.secondbit.org/uuid" 4.13 -) 4.14 - 4.15 -func init() { 4.16 - RegisterGrantType("authorization_code", GrantType{ 4.17 - Validate: authCodeGrantValidate, 4.18 - IssuesRefresh: true, 4.19 - ReturnToken: RenderJSONToken, 4.20 - }) 4.21 -} 4.22 - 4.23 -var ( 4.24 - // ErrNoGrantStore is returned when a Context tries to act on a grantStore without setting one first. 4.25 - ErrNoGrantStore = errors.New("no grantStore was specified for the Context") 4.26 - // ErrGrantNotFound is returned when a Grant is requested but not found in the grantStore. 4.27 - ErrGrantNotFound = errors.New("grant not found in grantStore") 4.28 - // ErrGrantAlreadyExists is returned when a Grant is added to a grantStore, but another Grant with the 4.29 - // same Code already exists in the grantStore. 4.30 - ErrGrantAlreadyExists = errors.New("grant already exists in grantStore") 4.31 -) 4.32 - 4.33 -// Grant represents an authorization grant made by a user to a Client, to 4.34 -// access user data within a defined Scope for a limited amount of time. 4.35 -type Grant struct { 4.36 - Code string 4.37 - Created time.Time 4.38 - ExpiresIn int32 4.39 - ClientID uuid.ID 4.40 - Scope string 4.41 - RedirectURI string 4.42 - State string 4.43 - ProfileID uuid.ID 4.44 -} 4.45 - 4.46 -type grantStore interface { 4.47 - getGrant(code string) (Grant, error) 4.48 - saveGrant(grant Grant) error 4.49 - deleteGrant(code string) error 4.50 -} 4.51 - 4.52 -func (m *memstore) getGrant(code string) (Grant, error) { 4.53 - m.grantLock.RLock() 4.54 - defer m.grantLock.RUnlock() 4.55 - grant, ok := m.grants[code] 4.56 - if !ok { 4.57 - return Grant{}, ErrGrantNotFound 4.58 - } 4.59 - return grant, nil 4.60 -} 4.61 - 4.62 -func (m *memstore) saveGrant(grant Grant) error { 4.63 - m.grantLock.Lock() 4.64 - defer m.grantLock.Unlock() 4.65 - _, ok := m.grants[grant.Code] 4.66 - if ok { 4.67 - return ErrGrantAlreadyExists 4.68 - } 4.69 - m.grants[grant.Code] = grant 4.70 - return nil 4.71 -} 4.72 - 4.73 -func (m *memstore) deleteGrant(code string) error { 4.74 - m.grantLock.Lock() 4.75 - defer m.grantLock.Unlock() 4.76 - _, ok := m.grants[code] 4.77 - if !ok { 4.78 - return ErrGrantNotFound 4.79 - } 4.80 - delete(m.grants, code) 4.81 - return nil 4.82 -} 4.83 - 4.84 -func authCodeGrantValidate(w http.ResponseWriter, r *http.Request, context Context) (scope string, profileID uuid.ID, valid bool) { 4.85 - enc := json.NewEncoder(w) 4.86 - code := r.PostFormValue("code") 4.87 - if code == "" { 4.88 - w.WriteHeader(http.StatusBadRequest) 4.89 - renderJSONError(enc, "invalid_request") 4.90 - return 4.91 - } 4.92 - clientID, success := verifyClient(w, r, true, context) 4.93 - if !success { 4.94 - return 4.95 - } 4.96 - grant, err := context.GetGrant(code) 4.97 - if err != nil { 4.98 - if err == ErrGrantNotFound { 4.99 - w.WriteHeader(http.StatusBadRequest) 4.100 - renderJSONError(enc, "invalid_grant") 4.101 - return 4.102 - } 4.103 - w.WriteHeader(http.StatusInternalServerError) 4.104 - renderJSONError(enc, "server_error") 4.105 - return 4.106 - } 4.107 - redirectURI := r.PostFormValue("redirect_uri") 4.108 - if grant.RedirectURI != redirectURI { 4.109 - w.WriteHeader(http.StatusBadRequest) 4.110 - renderJSONError(enc, "invalid_grant") 4.111 - return 4.112 - } 4.113 - if !grant.ClientID.Equal(clientID) { 4.114 - w.WriteHeader(http.StatusBadRequest) 4.115 - renderJSONError(enc, "invalid_grant") 4.116 - return 4.117 - } 4.118 - return grant.Scope, grant.ProfileID, true 4.119 -}
5.1 --- a/grant_test.go Sun Dec 07 02:54:42 2014 -0500 5.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 5.3 @@ -1,78 +0,0 @@ 5.4 -package auth 5.5 - 5.6 -import ( 5.7 - "testing" 5.8 - "time" 5.9 - 5.10 - "code.secondbit.org/uuid" 5.11 -) 5.12 - 5.13 -var grantStores = []grantStore{NewMemstore()} 5.14 - 5.15 -func compareGrants(grant1, grant2 Grant) (success bool, field string, grant1val, grant2val interface{}) { 5.16 - if grant1.Code != grant2.Code { 5.17 - return false, "code", grant1.Code, grant2.Code 5.18 - } 5.19 - if !grant1.Created.Equal(grant2.Created) { 5.20 - return false, "created", grant1.Created, grant2.Created 5.21 - } 5.22 - if grant1.ExpiresIn != grant2.ExpiresIn { 5.23 - return false, "expires in", grant1.ExpiresIn, grant2.ExpiresIn 5.24 - } 5.25 - if !grant1.ClientID.Equal(grant2.ClientID) { 5.26 - return false, "client ID", grant1.ClientID, grant2.ClientID 5.27 - } 5.28 - if grant1.Scope != grant2.Scope { 5.29 - return false, "scope", grant1.Scope, grant2.Scope 5.30 - } 5.31 - if grant1.RedirectURI != grant2.RedirectURI { 5.32 - return false, "redirect URI", grant1.RedirectURI, grant2.RedirectURI 5.33 - } 5.34 - if grant1.State != grant2.State { 5.35 - return false, "state", grant1.State, grant2.State 5.36 - } 5.37 - return true, "", nil, nil 5.38 -} 5.39 - 5.40 -func TestGrantStoreSuccess(t *testing.T) { 5.41 - t.Parallel() 5.42 - grant := Grant{ 5.43 - Code: "code", 5.44 - Created: time.Now(), 5.45 - ExpiresIn: 180, 5.46 - ClientID: uuid.NewID(), 5.47 - Scope: "scope", 5.48 - RedirectURI: "redirectURI", 5.49 - State: "state", 5.50 - } 5.51 - for _, store := range grantStores { 5.52 - err := store.saveGrant(grant) 5.53 - if err != nil { 5.54 - t.Errorf("Error saving grant to %T: %s", store, err) 5.55 - } 5.56 - err = store.saveGrant(grant) 5.57 - if err != ErrGrantAlreadyExists { 5.58 - t.Errorf("Expected ErrGrantAlreadyExists from %T, got %+v", store, err) 5.59 - } 5.60 - retrieved, err := store.getGrant(grant.Code) 5.61 - if err != nil { 5.62 - t.Errorf("Error retrieving grant from %T: %s", store, err) 5.63 - } 5.64 - match, field, expectation, result := compareGrants(grant, retrieved) 5.65 - if !match { 5.66 - t.Errorf("Expected `%v` in the `%s` field of grant retrieved from %T, got `%v`", expectation, field, store, result) 5.67 - } 5.68 - err = store.deleteGrant(grant.Code) 5.69 - if err != nil { 5.70 - t.Errorf("Error removing grant from %T: %s", store, err) 5.71 - } 5.72 - retrieved, err = store.getGrant(grant.Code) 5.73 - if err != ErrGrantNotFound { 5.74 - t.Errorf("Expected ErrGrantNotFound from %T, got %+v and %+v", store, retrieved, err) 5.75 - } 5.76 - err = store.deleteGrant(grant.Code) 5.77 - if err != ErrGrantNotFound { 5.78 - t.Errorf("Expected ErrGrantNotFound from %T, got %+v", store, err) 5.79 - } 5.80 - } 5.81 -}
6.1 --- a/memstore.go Sun Dec 07 02:54:42 2014 -0500 6.2 +++ b/memstore.go Sun Dec 07 03:40:25 2014 -0500 6.3 @@ -12,8 +12,8 @@ 6.4 profileTokenLookup map[string][]string 6.5 tokenLock sync.RWMutex 6.6 6.7 - grants map[string]Grant 6.8 - grantLock sync.RWMutex 6.9 + authCodes map[string]AuthorizationCode 6.10 + authCodeLock sync.RWMutex 6.11 6.12 clients map[string]Client 6.13 profileClientLookup map[string][]uuid.ID 6.14 @@ -42,7 +42,7 @@ 6.15 tokens: map[string]Token{}, 6.16 refreshTokenLookup: map[string]string{}, 6.17 profileTokenLookup: map[string][]string{}, 6.18 - grants: map[string]Grant{}, 6.19 + authCodes: map[string]AuthorizationCode{}, 6.20 clients: map[string]Client{}, 6.21 profileClientLookup: map[string][]uuid.ID{}, 6.22 endpoints: map[string][]Endpoint{},
7.1 --- a/oauth2.go Sun Dec 07 02:54:42 2014 -0500 7.2 +++ b/oauth2.go Sun Dec 07 03:40:25 2014 -0500 7.3 @@ -19,9 +19,9 @@ 7.4 ) 7.5 7.6 const ( 7.7 - authCookieName = "auth" 7.8 - defaultGrantExpiration = 600 // default to ten minute grant expirations 7.9 - getGrantTemplateName = "get_grant" 7.10 + authCookieName = "auth" 7.11 + defaultAuthorizationCodeExpiration = 600 // default to ten minute grant expirations 7.12 + getAuthorizationCodeTemplateName = "get_grant" 7.13 ) 7.14 7.15 var ( 7.16 @@ -192,13 +192,13 @@ 7.17 7.18 // RegisterOAuth2 adds handlers to the passed router to handle the OAuth2 endpoints. 7.19 func RegisterOAuth2(r *mux.Router, context Context) { 7.20 - r.Handle("/authorize", wrap(context, GetGrantHandler)) 7.21 + r.Handle("/authorize", wrap(context, GetAuthorizationCodeHandler)) 7.22 r.Handle("/token", wrap(context, GetTokenHandler)) 7.23 } 7.24 7.25 -// GetGrantHandler presents and processes the page for asking a user to grant access 7.26 +// GetAuthorizationCodeHandler presents and processes the page for asking a user to grant access 7.27 // to their data. See RFC 6749, Section 4.1. 7.28 -func GetGrantHandler(w http.ResponseWriter, r *http.Request, context Context) { 7.29 +func GetAuthorizationCodeHandler(w http.ResponseWriter, r *http.Request, context Context) { 7.30 session, err := checkCookie(r, context) 7.31 if err != nil { 7.32 if err == ErrNoSession || err == ErrInvalidSession { 7.33 @@ -206,7 +206,7 @@ 7.34 if redir == "" { 7.35 log.Println("No login URL configured.") 7.36 w.WriteHeader(http.StatusInternalServerError) 7.37 - context.Render(w, getGrantTemplateName, map[string]interface{}{ 7.38 + context.Render(w, getAuthorizationCodeTemplateName, map[string]interface{}{ 7.39 "internal_error": template.HTML("Missing login URL."), 7.40 }) 7.41 return 7.42 @@ -216,14 +216,14 @@ 7.43 } 7.44 log.Println(err.Error()) 7.45 w.WriteHeader(http.StatusInternalServerError) 7.46 - context.Render(w, getGrantTemplateName, map[string]interface{}{ 7.47 + context.Render(w, getAuthorizationCodeTemplateName, map[string]interface{}{ 7.48 "internal_error": template.HTML(err.Error()), 7.49 }) 7.50 return 7.51 } 7.52 if r.URL.Query().Get("client_id") == "" { 7.53 w.WriteHeader(http.StatusBadRequest) 7.54 - context.Render(w, getGrantTemplateName, map[string]interface{}{ 7.55 + context.Render(w, getAuthorizationCodeTemplateName, map[string]interface{}{ 7.56 "error": template.HTML("Client ID must be specified in the request."), 7.57 }) 7.58 return 7.59 @@ -231,7 +231,7 @@ 7.60 clientID, err := uuid.Parse(r.URL.Query().Get("client_id")) 7.61 if err != nil { 7.62 w.WriteHeader(http.StatusBadRequest) 7.63 - context.Render(w, getGrantTemplateName, map[string]interface{}{ 7.64 + context.Render(w, getAuthorizationCodeTemplateName, map[string]interface{}{ 7.65 "error": template.HTML("client_id is not a valid Client ID."), 7.66 }) 7.67 return 7.68 @@ -240,7 +240,7 @@ 7.69 redirectURL, err := url.Parse(redirectURI) 7.70 if err != nil { 7.71 w.WriteHeader(http.StatusBadRequest) 7.72 - context.Render(w, getGrantTemplateName, map[string]interface{}{ 7.73 + context.Render(w, getAuthorizationCodeTemplateName, map[string]interface{}{ 7.74 "error": template.HTML("The redirect_uri specified is not valid."), 7.75 }) 7.76 return 7.77 @@ -249,13 +249,13 @@ 7.78 if err != nil { 7.79 if err == ErrClientNotFound { 7.80 w.WriteHeader(http.StatusBadRequest) 7.81 - context.Render(w, getGrantTemplateName, map[string]interface{}{ 7.82 + context.Render(w, getAuthorizationCodeTemplateName, map[string]interface{}{ 7.83 "error": template.HTML("The specified Client couldn’t be found."), 7.84 }) 7.85 } else { 7.86 log.Println(err.Error()) 7.87 w.WriteHeader(http.StatusInternalServerError) 7.88 - context.Render(w, getGrantTemplateName, map[string]interface{}{ 7.89 + context.Render(w, getAuthorizationCodeTemplateName, map[string]interface{}{ 7.90 "internal_error": template.HTML(err.Error()), 7.91 }) 7.92 } 7.93 @@ -267,7 +267,7 @@ 7.94 if err != nil { 7.95 log.Println(err.Error()) 7.96 w.WriteHeader(http.StatusInternalServerError) 7.97 - context.Render(w, getGrantTemplateName, map[string]interface{}{ 7.98 + context.Render(w, getAuthorizationCodeTemplateName, map[string]interface{}{ 7.99 "internal_error": template.HTML(err.Error()), 7.100 }) 7.101 return 7.102 @@ -279,7 +279,7 @@ 7.103 if err != nil { 7.104 log.Println(err.Error()) 7.105 w.WriteHeader(http.StatusInternalServerError) 7.106 - context.Render(w, getGrantTemplateName, map[string]interface{}{ 7.107 + context.Render(w, getAuthorizationCodeTemplateName, map[string]interface{}{ 7.108 "internal_error": template.HTML(err.Error()), 7.109 }) 7.110 return 7.111 @@ -292,7 +292,7 @@ 7.112 if err != nil { 7.113 log.Println(err.Error()) 7.114 w.WriteHeader(http.StatusInternalServerError) 7.115 - context.Render(w, getGrantTemplateName, map[string]interface{}{ 7.116 + context.Render(w, getAuthorizationCodeTemplateName, map[string]interface{}{ 7.117 "internal_error": template.HTML(err.Error()), 7.118 }) 7.119 return 7.120 @@ -309,7 +309,7 @@ 7.121 } 7.122 if !validURI { 7.123 w.WriteHeader(http.StatusBadRequest) 7.124 - context.Render(w, getGrantTemplateName, map[string]interface{}{ 7.125 + context.Render(w, getAuthorizationCodeTemplateName, map[string]interface{}{ 7.126 "error": template.HTML("The redirect_uri specified is not valid."), 7.127 }) 7.128 return 7.129 @@ -328,17 +328,17 @@ 7.130 // BUG(paddy): We need to implement CSRF protection when obtaining a grant code. 7.131 if r.PostFormValue("grant") == "approved" { 7.132 code := uuid.NewID().String() 7.133 - grant := Grant{ 7.134 + authCode := AuthorizationCode{ 7.135 Code: code, 7.136 Created: time.Now(), 7.137 - ExpiresIn: defaultGrantExpiration, 7.138 + ExpiresIn: defaultAuthorizationCodeExpiration, 7.139 ClientID: clientID, 7.140 Scope: scope, 7.141 RedirectURI: r.URL.Query().Get("redirect_uri"), 7.142 State: state, 7.143 ProfileID: session.ProfileID, 7.144 } 7.145 - err := context.SaveGrant(grant) 7.146 + err := context.SaveAuthorizationCode(authCode) 7.147 if err != nil { 7.148 q := redirectURL.Query() 7.149 q.Add("error", "server_error") 7.150 @@ -371,7 +371,7 @@ 7.151 return 7.152 } 7.153 w.WriteHeader(http.StatusOK) 7.154 - context.Render(w, getGrantTemplateName, map[string]interface{}{ 7.155 + context.Render(w, getAuthorizationCodeTemplateName, map[string]interface{}{ 7.156 "client": client, 7.157 "redirectURL": redirectURL, 7.158 "scope": scope,
8.1 --- a/oauth2_test.go Sun Dec 07 02:54:42 2014 -0500 8.2 +++ b/oauth2_test.go Sun Dec 07 03:40:25 2014 -0500 8.3 @@ -26,16 +26,16 @@ 8.4 u.RawQuery = q.Encode() 8.5 } 8.6 8.7 -func TestGetGrantCodeSuccess(t *testing.T) { 8.8 +func TestGetAuthorizationCodeCodeSuccess(t *testing.T) { 8.9 t.Parallel() 8.10 store := NewMemstore() 8.11 testContext := Context{ 8.12 - template: template.Must(template.New(getGrantTemplateName).Parse("Get auth grant")), 8.13 - clients: store, 8.14 - grants: store, 8.15 - profiles: store, 8.16 - tokens: store, 8.17 - sessions: store, 8.18 + template: template.Must(template.New(getAuthorizationCodeTemplateName).Parse("Get auth grant")), 8.19 + clients: store, 8.20 + authCodes: store, 8.21 + profiles: store, 8.22 + tokens: store, 8.23 + sessions: store, 8.24 } 8.25 client := Client{ 8.26 ID: uuid.NewID(), 8.27 @@ -108,7 +108,7 @@ 8.28 req.Method = "GET" 8.29 req.Body = nil 8.30 req.Header.Del("Content-Type") 8.31 - GetGrantHandler(w, req, testContext) 8.32 + GetAuthorizationCodeHandler(w, req, testContext) 8.33 if w.Code != http.StatusOK { 8.34 t.Errorf("Expected status code to be %d, got %d for %s", http.StatusOK, w.Code, req.URL.String()) 8.35 } 8.36 @@ -122,7 +122,7 @@ 8.37 data.Set("grant", "approved") 8.38 body := bytes.NewBufferString(data.Encode()) 8.39 req.Body = ioutil.NopCloser(body) 8.40 - GetGrantHandler(w, req, testContext) 8.41 + GetAuthorizationCodeHandler(w, req, testContext) 8.42 if w.Code != http.StatusFound { 8.43 t.Errorf("Expected status code to be %d, got %d for %s", http.StatusFound, w.Code, req.URL.String()) 8.44 } 8.45 @@ -135,10 +135,10 @@ 8.46 if red.Query().Get("code") == "" { 8.47 t.Fatalf(`Expected code param in redirect URL to be set, but it wasn't for %s`, req.URL.String()) 8.48 } 8.49 - if _, err := testContext.GetGrant(red.Query().Get("code")); err != nil { 8.50 + if _, err := testContext.GetAuthorizationCode(red.Query().Get("code")); err != nil { 8.51 t.Fatalf(`Unexpected error "%s: retrieving the grant "%s" supplied in the redirect URL for %s`, err, red.Query().Get("code"), req.URL.String()) 8.52 } 8.53 - err = testContext.DeleteGrant(red.Query().Get("code")) 8.54 + err = testContext.DeleteAuthorizationCode(red.Query().Get("code")) 8.55 if err != nil { 8.56 t.Logf(`Unexpected error "%s" deleting grant "%s" for %s`, err, red.Query().Get("code"), req.URL.String()) 8.57 } 8.58 @@ -153,16 +153,16 @@ 8.59 } 8.60 } 8.61 8.62 -func TestGetGrantCodeInvalidClient(t *testing.T) { 8.63 +func TestGetAuthorizationCodeCodeInvalidClient(t *testing.T) { 8.64 t.Parallel() 8.65 store := NewMemstore() 8.66 testContext := Context{ 8.67 - template: template.Must(template.New(getGrantTemplateName).Parse("{{ .error }}")), 8.68 - clients: store, 8.69 - grants: store, 8.70 - profiles: store, 8.71 - tokens: store, 8.72 - sessions: store, 8.73 + template: template.Must(template.New(getAuthorizationCodeTemplateName).Parse("{{ .error }}")), 8.74 + clients: store, 8.75 + authCodes: store, 8.76 + profiles: store, 8.77 + tokens: store, 8.78 + sessions: store, 8.79 } 8.80 client := Client{ 8.81 ID: uuid.NewID(), 8.82 @@ -197,7 +197,7 @@ 8.83 Value: session.ID, 8.84 } 8.85 req.AddCookie(cookie) 8.86 - GetGrantHandler(w, req, testContext) 8.87 + GetAuthorizationCodeHandler(w, req, testContext) 8.88 if w.Code != http.StatusBadRequest { 8.89 t.Errorf("Expected status code to be %d, got %d", http.StatusBadRequest, w.Code) 8.90 } 8.91 @@ -207,7 +207,7 @@ 8.92 w = httptest.NewRecorder() 8.93 params.Set("client_id", "Not an ID") 8.94 req.URL.RawQuery = params.Encode() 8.95 - GetGrantHandler(w, req, testContext) 8.96 + GetAuthorizationCodeHandler(w, req, testContext) 8.97 if w.Code != http.StatusBadRequest { 8.98 t.Errorf("Expected status code to be %d, got %d", http.StatusBadRequest, w.Code) 8.99 } 8.100 @@ -217,7 +217,7 @@ 8.101 w = httptest.NewRecorder() 8.102 params.Set("client_id", uuid.NewID().String()) 8.103 req.URL.RawQuery = params.Encode() 8.104 - GetGrantHandler(w, req, testContext) 8.105 + GetAuthorizationCodeHandler(w, req, testContext) 8.106 if w.Code != http.StatusBadRequest { 8.107 t.Errorf("Expected status code to be %d, got %d", http.StatusBadRequest, w.Code) 8.108 } 8.109 @@ -226,16 +226,16 @@ 8.110 } 8.111 } 8.112 8.113 -func TestGetGrantCodeInvalidURI(t *testing.T) { 8.114 +func TestGetAuthorizationCodeCodeInvalidURI(t *testing.T) { 8.115 t.Parallel() 8.116 store := NewMemstore() 8.117 testContext := Context{ 8.118 - template: template.Must(template.New(getGrantTemplateName).Parse("{{ .error }}")), 8.119 - clients: store, 8.120 - grants: store, 8.121 - profiles: store, 8.122 - tokens: store, 8.123 - sessions: store, 8.124 + template: template.Must(template.New(getAuthorizationCodeTemplateName).Parse("{{ .error }}")), 8.125 + clients: store, 8.126 + authCodes: store, 8.127 + profiles: store, 8.128 + tokens: store, 8.129 + sessions: store, 8.130 } 8.131 client := Client{ 8.132 ID: uuid.NewID(), 8.133 @@ -274,7 +274,7 @@ 8.134 params.Set("response_type", "code") 8.135 params.Set("client_id", client.ID.String()) 8.136 req.URL.RawQuery = params.Encode() 8.137 - GetGrantHandler(w, req, testContext) 8.138 + GetAuthorizationCodeHandler(w, req, testContext) 8.139 if w.Code != http.StatusBadRequest { 8.140 t.Errorf("Expected status code to be %d, got %d", http.StatusBadRequest, w.Code) 8.141 } 8.142 @@ -294,7 +294,7 @@ 8.143 w = httptest.NewRecorder() 8.144 params.Set("redirect_uri", "https://test.secondbit.org/wrong") 8.145 req.URL.RawQuery = params.Encode() 8.146 - GetGrantHandler(w, req, testContext) 8.147 + GetAuthorizationCodeHandler(w, req, testContext) 8.148 if w.Code != http.StatusBadRequest { 8.149 t.Errorf("Expected status code to be %d, got %d", http.StatusBadRequest, w.Code) 8.150 } 8.151 @@ -314,7 +314,7 @@ 8.152 w = httptest.NewRecorder() 8.153 params.Set("redirect_uri", "") 8.154 req.URL.RawQuery = params.Encode() 8.155 - GetGrantHandler(w, req, testContext) 8.156 + GetAuthorizationCodeHandler(w, req, testContext) 8.157 if w.Code != http.StatusBadRequest { 8.158 t.Errorf("Expected status code to be %d, got %d", http.StatusBadRequest, w.Code) 8.159 } 8.160 @@ -324,7 +324,7 @@ 8.161 w = httptest.NewRecorder() 8.162 params.Set("redirect_uri", "://not a URL") 8.163 req.URL.RawQuery = params.Encode() 8.164 - GetGrantHandler(w, req, testContext) 8.165 + GetAuthorizationCodeHandler(w, req, testContext) 8.166 if w.Code != http.StatusBadRequest { 8.167 t.Errorf("Expected status code to be %d, got %d", http.StatusBadRequest, w.Code) 8.168 } 8.169 @@ -333,16 +333,16 @@ 8.170 } 8.171 } 8.172 8.173 -func TestGetGrantCodeInvalidResponseType(t *testing.T) { 8.174 +func TestGetAuthorizationCodeCodeInvalidResponseType(t *testing.T) { 8.175 t.Parallel() 8.176 store := NewMemstore() 8.177 testContext := Context{ 8.178 - template: template.Must(template.New(getGrantTemplateName).Parse("{{ .error }}")), 8.179 - clients: store, 8.180 - grants: store, 8.181 - profiles: store, 8.182 - tokens: store, 8.183 - sessions: store, 8.184 + template: template.Must(template.New(getAuthorizationCodeTemplateName).Parse("{{ .error }}")), 8.185 + clients: store, 8.186 + authCodes: store, 8.187 + profiles: store, 8.188 + tokens: store, 8.189 + sessions: store, 8.190 } 8.191 client := Client{ 8.192 ID: uuid.NewID(), 8.193 @@ -396,7 +396,7 @@ 8.194 params.Set("state", "my super secure state string") 8.195 req.URL.RawQuery = params.Encode() 8.196 w := httptest.NewRecorder() 8.197 - GetGrantHandler(w, req, testContext) 8.198 + GetAuthorizationCodeHandler(w, req, testContext) 8.199 if w.Code != http.StatusFound { 8.200 t.Errorf("Expected status code to be %d, got %d", http.StatusFound, w.Code) 8.201 } 8.202 @@ -418,7 +418,7 @@ 8.203 } 8.204 stripParam("response_type", req.URL) 8.205 w = httptest.NewRecorder() 8.206 - GetGrantHandler(w, req, testContext) 8.207 + GetAuthorizationCodeHandler(w, req, testContext) 8.208 if w.Code != http.StatusFound { 8.209 t.Errorf("Expected status code to be %d, got %d", http.StatusFound, w.Code) 8.210 } 8.211 @@ -440,16 +440,16 @@ 8.212 } 8.213 } 8.214 8.215 -func TestGetGrantCodeDenied(t *testing.T) { 8.216 +func TestGetAuthorizationCodeCodeDenied(t *testing.T) { 8.217 t.Parallel() 8.218 store := NewMemstore() 8.219 testContext := Context{ 8.220 - template: template.Must(template.New(getGrantTemplateName).Parse("{{ .error }}")), 8.221 - clients: store, 8.222 - grants: store, 8.223 - profiles: store, 8.224 - tokens: store, 8.225 - sessions: store, 8.226 + template: template.Must(template.New(getAuthorizationCodeTemplateName).Parse("{{ .error }}")), 8.227 + clients: store, 8.228 + authCodes: store, 8.229 + profiles: store, 8.230 + tokens: store, 8.231 + sessions: store, 8.232 } 8.233 client := Client{ 8.234 ID: uuid.NewID(), 8.235 @@ -507,7 +507,7 @@ 8.236 req.Body = ioutil.NopCloser(bytes.NewBufferString(data.Encode())) 8.237 req.Method = "POST" 8.238 w := httptest.NewRecorder() 8.239 - GetGrantHandler(w, req, testContext) 8.240 + GetAuthorizationCodeHandler(w, req, testContext) 8.241 if w.Code != http.StatusFound { 8.242 t.Errorf("Expected status code to be %d, got %d", http.StatusFound, w.Code) 8.243 } 8.244 @@ -529,14 +529,14 @@ 8.245 } 8.246 } 8.247 8.248 -func TestGetGrantCodeLoginRedirect(t *testing.T) { 8.249 +func TestGetAuthorizationCodeCodeLoginRedirect(t *testing.T) { 8.250 t.Parallel() 8.251 req, err := http.NewRequest("GET", "https://test.auth.secondbit.org/oauth2/grant", nil) 8.252 if err != nil { 8.253 t.Fatal("Can't build request:", err) 8.254 } 8.255 w := httptest.NewRecorder() 8.256 - GetGrantHandler(w, req, Context{template: template.Must(template.New(getGrantTemplateName).Parse("{{ .internal_error }}"))}) 8.257 + GetAuthorizationCodeHandler(w, req, Context{template: template.Must(template.New(getAuthorizationCodeTemplateName).Parse("{{ .internal_error }}"))}) 8.258 if w.Code != http.StatusInternalServerError { 8.259 t.Errorf("Expected status code to be %d, got %d", http.StatusInternalServerError, w.Code) 8.260 } 8.261 @@ -552,7 +552,7 @@ 8.262 loginURI: uri, 8.263 } 8.264 w = httptest.NewRecorder() 8.265 - GetGrantHandler(w, req, testContext) 8.266 + GetAuthorizationCodeHandler(w, req, testContext) 8.267 if w.Code != http.StatusFound { 8.268 t.Errorf("Expected status code to be %d, got %d", http.StatusFound, w.Code) 8.269 } 8.270 @@ -752,9 +752,9 @@ 8.271 t.Parallel() 8.272 store := NewMemstore() 8.273 context := Context{ 8.274 - clients: store, 8.275 - grants: store, 8.276 - tokens: store, 8.277 + clients: store, 8.278 + authCodes: store, 8.279 + tokens: store, 8.280 } 8.281 client := Client{ 8.282 ID: uuid.NewID(), 8.283 @@ -765,7 +765,7 @@ 8.284 Website: "https://client.secondbit.org/", 8.285 Type: "confidential", 8.286 } 8.287 - grant := Grant{ 8.288 + authCode := AuthorizationCode{ 8.289 Code: "testcode", 8.290 Created: time.Now(), 8.291 ExpiresIn: 600, 8.292 @@ -775,9 +775,9 @@ 8.293 State: "teststate", 8.294 ProfileID: uuid.NewID(), 8.295 } 8.296 - err := context.SaveGrant(grant) 8.297 + err := context.SaveAuthorizationCode(authCode) 8.298 if err != nil { 8.299 - t.Error("Error saving grant:", err) 8.300 + t.Error("Error saving auth code:", err) 8.301 } 8.302 err = context.SaveClient(client) 8.303 if err != nil { 8.304 @@ -785,8 +785,8 @@ 8.305 } 8.306 data := url.Values{} 8.307 data.Set("grant_type", "authorization_code") 8.308 - data.Set("code", grant.Code) 8.309 - data.Set("redirect_uri", grant.RedirectURI) 8.310 + data.Set("code", authCode.Code) 8.311 + data.Set("redirect_uri", authCode.RedirectURI) 8.312 body := bytes.NewBufferString(data.Encode()) 8.313 req, err := http.NewRequest("POST", "https://auth.secondbit.org/", ioutil.NopCloser(body)) 8.314 if err != nil { 8.315 @@ -814,7 +814,7 @@ 8.316 if resp.ExpiresIn == 0 { 8.317 t.Error("Got blank expires in back") 8.318 } 8.319 - tokens, err := context.GetTokensByProfileID(grant.ProfileID, 1, 0) 8.320 + tokens, err := context.GetTokensByProfileID(authCode.ProfileID, 1, 0) 8.321 if err != nil { 8.322 t.Error("Error retrieving token:", err) 8.323 }