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