auth

Paddy 2014-10-22 Parent:116342ffc65f Child:e45bfa2abc00

56:a5987795707e Go to Latest

auth/http.go

Actually validate grant requests. Write the logic to validate grant requests and stub out the rendering/error handling/redirecting locations. Finally, we get to the good stuff: implementing the specification. Write some tests to verify that granting requests works the way we think it does.

History
paddy@51 1 package auth
paddy@51 2
paddy@51 3 import (
paddy@51 4 "net/http"
paddy@56 5
paddy@56 6 "code.secondbit.org/uuid"
paddy@51 7 )
paddy@51 8
paddy@51 9 const getGrantTemplateName = "get_grant"
paddy@51 10
paddy@51 11 func GetGrantHandler(w http.ResponseWriter, r *http.Request, context Context) {
paddy@56 12 if r.URL.Query().Get("client_id") == "" {
paddy@56 13 w.WriteHeader(http.StatusBadRequest)
paddy@56 14 context.Render(w, getGrantTemplateName, map[string]interface{}{
paddy@56 15 "error": "Client ID must be specified in the request.",
paddy@56 16 })
paddy@56 17 return
paddy@56 18 }
paddy@56 19 clientID, err := uuid.Parse(r.URL.Query().Get("client_id"))
paddy@56 20 if err != nil {
paddy@56 21 w.WriteHeader(http.StatusBadRequest)
paddy@56 22 context.Render(w, getGrantTemplateName, map[string]interface{}{
paddy@56 23 "error": "client_id is not a valid Client ID.",
paddy@56 24 })
paddy@56 25 return
paddy@56 26 }
paddy@56 27 client, err := context.GetClient(clientID)
paddy@56 28 if err != nil {
paddy@56 29 w.WriteHeader(http.StatusInternalServerError)
paddy@56 30 context.Render(w, getGrantTemplateName, map[string]interface{}{
paddy@56 31 "internal_error": err,
paddy@56 32 })
paddy@56 33 return
paddy@56 34 }
paddy@56 35 // whether a redirect URI is valid or not depends on the number of endpoints
paddy@56 36 // the client has registered
paddy@56 37 numEndpoints, err := context.CountEndpoints(clientID)
paddy@56 38 if err != nil {
paddy@56 39 w.WriteHeader(http.StatusInternalServerError)
paddy@56 40 context.Render(w, getGrantTemplateName, map[string]interface{}{
paddy@56 41 "internal_error": err,
paddy@56 42 })
paddy@56 43 return
paddy@56 44 }
paddy@56 45 redirectURI := r.URL.Query().Get("redirect_uri")
paddy@56 46 var validURI bool
paddy@56 47 if redirectURI != "" && numEndpoints > 1 {
paddy@56 48 // if there's more than one registered endpoint, we need to match the
paddy@56 49 // entire thing, character for character. So use strict checking.
paddy@56 50 validURI, err = context.CheckEndpoint(clientID, redirectURI, true)
paddy@56 51 if err != nil {
paddy@56 52 w.WriteHeader(http.StatusInternalServerError)
paddy@56 53 context.Render(w, getGrantTemplateName, map[string]interface{}{
paddy@56 54 "internal_error": err,
paddy@56 55 })
paddy@56 56 return
paddy@56 57 }
paddy@56 58 } else if redirectURI != "" && numEndpoints == 1 {
paddy@56 59 // if there's exactly one endpoint, we can match only the prefix of it,
paddy@56 60 // so don't use strict checking.
paddy@56 61 validURI, err = context.CheckEndpoint(clientID, redirectURI, false)
paddy@56 62 if err != nil {
paddy@56 63 w.WriteHeader(http.StatusInternalServerError)
paddy@56 64 context.Render(w, getGrantTemplateName, map[string]interface{}{
paddy@56 65 "internal_error": err,
paddy@56 66 })
paddy@56 67 return
paddy@56 68 }
paddy@56 69 } else if redirectURI == "" && numEndpoints == 1 {
paddy@56 70 // if we don't specify the endpoint and there's only one endpoint, the
paddy@56 71 // request is valid, and we're redirecting to that one endpoint
paddy@56 72 validURI = true
paddy@56 73 endpoints, err := context.ListEndpoints(clientID, 1, 0)
paddy@56 74 if err != nil {
paddy@56 75 w.WriteHeader(http.StatusInternalServerError)
paddy@56 76 context.Render(w, getGrantTemplateName, map[string]interface{}{
paddy@56 77 "internal_error": err,
paddy@56 78 })
paddy@56 79 return
paddy@56 80 }
paddy@56 81 if len(endpoints) != 1 {
paddy@56 82 validURI = false
paddy@56 83 } else {
paddy@56 84 redirectURI = endpoints[0].URI.String()
paddy@56 85 }
paddy@56 86 } else {
paddy@56 87 validURI = false
paddy@56 88 }
paddy@56 89 if !validURI {
paddy@56 90 w.WriteHeader(http.StatusBadRequest)
paddy@56 91 context.Render(w, getGrantTemplateName, map[string]interface{}{
paddy@56 92 "error": "The redirect_uri specified is not valid.",
paddy@56 93 })
paddy@56 94 return
paddy@56 95 }
paddy@56 96 if r.URL.Query().Get("response_type") != "code" {
paddy@56 97 // TODO: redirect error
paddy@56 98 }
paddy@56 99 //scope := r.URL.Query().Get("scope")
paddy@56 100 //state := r.URL.Query().Get("state")
paddy@56 101 if r.Method == "POST" {
paddy@56 102 // TODO: CSRF protection
paddy@56 103 if r.PostFormValue("grant") == "approved" {
paddy@56 104 // TODO: redirect
paddy@56 105 } else {
paddy@56 106 // TODO: redirect error
paddy@56 107 }
paddy@56 108 }
paddy@51 109 w.WriteHeader(http.StatusOK)
paddy@56 110 context.Render(w, getGrantTemplateName, map[string]interface{}{
paddy@56 111 "client": client,
paddy@56 112 })
paddy@51 113 }