auth

Paddy 2015-01-18 Parent:e000b1c24fc0 Child:8ecb60d29b0d

123:0a1e16b9c141 Go to Latest

auth/request_test.go

Refactor verifyClient, implement refresh tokens. Refactor verifyClient into verifyClient and getClientAuth. We moved verifyClient out of each of the GrantType's validation functions and into the access token endpoint, where it will be called before the GrantType's validation function. Yay, less code repetition. And seeing as we always want to verify the client, that seems like a good way to prevent things like 118a69954621 from happening. This did, however, force us to add an AllowsPublic property to the GrantType, so the token endpoint knows whether or not a public Client is valid for any given GrantType. We also implemented the refresh token grant type, which required adding ClientID and RefreshRevoked as properties on the Token type. We need ClientID because we need to constrain refresh tokens to the client that issued them. We also should probably keep track of which tokens belong to which clients, just as a general rule of thumb. RefreshRevoked had to be created, next to Revoked, because the AccessToken could be revoked and the RefreshToken still valid, or vice versa. Notably, when you issue a new refresh token, the old one is revoked, but the access token is still valid. It remains to be seen whether this is a good way to track things or not. The number of duplicated properties lead me to believe our type is not a great representation of the underlying concepts.

History
paddy@116 1 package auth
paddy@116 2
paddy@116 3 import "fmt"
paddy@116 4
paddy@116 5 func compareErrors(err1, err2 requestError) (success bool, field string, val1, val2 interface{}) {
paddy@116 6 if err1.Slug != err2.Slug {
paddy@116 7 return false, "Slug", err1.Slug, err2.Slug
paddy@116 8 }
paddy@116 9 if err1.Field != err2.Field {
paddy@116 10 return false, "Field", err1.Field, err2.Field
paddy@116 11 }
paddy@116 12 if err1.Param != err2.Param {
paddy@116 13 return false, "Param", err1.Param, err2.Param
paddy@116 14 }
paddy@116 15 if err1.Header != err2.Header {
paddy@116 16 return false, "Header", err1.Header, err2.Header
paddy@116 17 }
paddy@116 18 return true, "", nil, nil
paddy@116 19 }
paddy@116 20
paddy@116 21 func compareResponses(resp1, resp2 response) (success bool, field string, val1, val2 interface{}) {
paddy@116 22 if len(resp1.Errors) != len(resp2.Errors) {
paddy@116 23 return false, "Errors", resp1.Errors, resp2.Errors
paddy@116 24 }
paddy@116 25 if len(resp1.Logins) != len(resp2.Logins) {
paddy@116 26 return false, "Logins", resp1.Logins, resp2.Logins
paddy@116 27 }
paddy@116 28 if len(resp1.Profiles) != len(resp2.Profiles) {
paddy@116 29 return false, "Profiles", resp1.Profiles, resp2.Profiles
paddy@116 30 }
paddy@116 31 if len(resp1.Clients) != len(resp2.Clients) {
paddy@116 32 return false, "Clients", resp1.Clients, resp2.Clients
paddy@116 33 }
paddy@116 34 if len(resp1.Endpoints) != len(resp2.Endpoints) {
paddy@116 35 return false, "Endpoints", resp1.Endpoints, resp2.Endpoints
paddy@116 36 }
paddy@116 37 for pos := range resp1.Errors {
paddy@116 38 success, field, val1, val2 = compareErrors(resp1.Errors[pos], resp2.Errors[pos])
paddy@116 39 if !success {
paddy@116 40 field = fmt.Sprintf("Error %d %s", pos, field)
paddy@116 41 return
paddy@116 42 }
paddy@116 43 }
paddy@116 44 for pos := range resp1.Logins {
paddy@116 45 success, field, val1, val2 = compareLogins(resp1.Logins[pos], resp2.Logins[pos])
paddy@116 46 if !success {
paddy@116 47 field = fmt.Sprintf("Login %d %s", pos, field)
paddy@116 48 return
paddy@116 49 }
paddy@116 50 }
paddy@116 51 for pos := range resp1.Profiles {
paddy@116 52 success, field, val1, val2 = compareProfiles(resp1.Profiles[pos], resp2.Profiles[pos])
paddy@116 53 if !success {
paddy@116 54 field = fmt.Sprintf("Profile %d %s", pos, field)
paddy@116 55 return
paddy@116 56 }
paddy@116 57 }
paddy@116 58 for pos := range resp1.Clients {
paddy@116 59 success, field, val1, val2 = compareClients(resp1.Clients[pos], resp2.Clients[pos])
paddy@116 60 if !success {
paddy@116 61 field = fmt.Sprintf("Client %d %s", pos, field)
paddy@116 62 return
paddy@116 63 }
paddy@116 64 }
paddy@116 65 for pos := range resp1.Endpoints {
paddy@116 66 success, field, val1, val2 = compareEndpoints(resp1.Endpoints[pos], resp2.Endpoints[pos])
paddy@116 67 if !success {
paddy@116 68 field = fmt.Sprintf("Endpoint %d %s", pos, field)
paddy@116 69 return
paddy@116 70 }
paddy@116 71 }
paddy@116 72 return true, "", nil, nil
paddy@116 73 }
paddy@116 74
paddy@116 75 func fillInServerGenerated(expectation, result response) {
paddy@116 76 if len(expectation.Profiles) > 0 {
paddy@116 77 for pos, profile := range expectation.Profiles {
paddy@116 78 profile.ID = result.Profiles[pos].ID
paddy@116 79 profile.Created = result.Profiles[pos].Created
paddy@116 80 profile.LastSeen = result.Profiles[pos].LastSeen
paddy@116 81 expectation.Profiles[pos] = profile
paddy@116 82 }
paddy@116 83 }
paddy@116 84 if len(expectation.Logins) > 0 {
paddy@116 85 for pos, login := range expectation.Logins {
paddy@116 86 login.ProfileID = result.Logins[pos].ProfileID
paddy@116 87 login.Created = result.Logins[pos].Created
paddy@116 88 login.LastUsed = result.Logins[pos].LastUsed
paddy@116 89 expectation.Logins[pos] = login
paddy@116 90 }
paddy@116 91 }
paddy@116 92 if len(expectation.Clients) > 0 {
paddy@116 93 for pos, client := range expectation.Clients {
paddy@116 94 client.ID = result.Clients[pos].ID
paddy@116 95 client.Secret = result.Clients[pos].Secret
paddy@116 96 client.OwnerID = result.Clients[pos].OwnerID
paddy@116 97 expectation.Clients[pos] = client
paddy@116 98 }
paddy@116 99 }
paddy@116 100 if len(expectation.Endpoints) > 0 {
paddy@116 101 for pos, endpoint := range expectation.Endpoints {
paddy@116 102 endpoint.ID = result.Endpoints[pos].ID
paddy@116 103 endpoint.ClientID = result.Endpoints[pos].ClientID
paddy@116 104 endpoint.Added = result.Endpoints[pos].Added
paddy@116 105 expectation.Endpoints[pos] = endpoint
paddy@116 106 }
paddy@116 107 }
paddy@116 108 }