auth
auth/context.go
Implement CSRF prevention and pass info to confirmation. Implement CSRF prevention using the nosurf package. Note that the handler still needs to be wrapped before this will work. Pass info on the authorization being requested (namely the client and the scope) to the RenderConfirmation page so that the user can make an educated decision.
| paddy@6 | 1 package auth |
| paddy@0 | 2 |
| paddy@10 | 3 import ( |
| paddy@15 | 4 "encoding/json" |
| paddy@15 | 5 "html/template" |
| paddy@10 | 6 "io" |
| paddy@10 | 7 "log" |
| paddy@17 | 8 "net/http" |
| paddy@17 | 9 |
| paddy@17 | 10 "github.com/justinas/nosurf" |
| paddy@10 | 11 ) |
| paddy@1 | 12 |
| paddy@0 | 13 type Context struct { |
| paddy@15 | 14 Config ServerConfig |
| paddy@15 | 15 Clients ClientStore |
| paddy@15 | 16 Tokens TokenStore |
| paddy@15 | 17 Profiles ProfileStore |
| paddy@15 | 18 Log *log.Logger |
| paddy@15 | 19 Templates Templates |
| paddy@15 | 20 } |
| paddy@15 | 21 |
| paddy@15 | 22 type Templates struct { |
| paddy@15 | 23 Error *template.Template |
| paddy@15 | 24 Confirmation *template.Template |
| paddy@15 | 25 Login *template.Template |
| paddy@15 | 26 } |
| paddy@15 | 27 |
| paddy@15 | 28 type jsonError struct { |
| paddy@15 | 29 Error string `json:"error,omitempty"` |
| paddy@15 | 30 Description string `json:"error_description,omitempty"` |
| paddy@15 | 31 URI string `json:"error_uri,omitempty"` |
| paddy@15 | 32 State string `json:"state,omitempty"` |
| paddy@0 | 33 } |
| paddy@1 | 34 |
| paddy@1 | 35 func (c Context) RenderError(w io.Writer, err error) { |
| paddy@15 | 36 if c.Templates.Error == nil { |
| paddy@15 | 37 log.Println("Error template is nil, can't render error.") |
| paddy@15 | 38 return |
| paddy@15 | 39 } |
| paddy@15 | 40 renderErr := c.Templates.Error.Execute(w, map[string]interface{}{ |
| paddy@15 | 41 "err": err, |
| paddy@15 | 42 }) |
| paddy@15 | 43 if renderErr != nil { |
| paddy@15 | 44 log.Printf("Error executing error template (oh, the irony): %s\n", renderErr) |
| paddy@15 | 45 return |
| paddy@15 | 46 } |
| paddy@1 | 47 } |
| paddy@1 | 48 |
| paddy@3 | 49 func (c Context) RenderJSONError(w io.Writer, code, description, baseURI string) { |
| paddy@15 | 50 d, err := json.Marshal(jsonError{ |
| paddy@15 | 51 Error: code, |
| paddy@15 | 52 Description: description, |
| paddy@15 | 53 URI: baseURI, |
| paddy@15 | 54 }) |
| paddy@15 | 55 if err != nil { |
| paddy@15 | 56 log.Printf("Error marshalling json error (oh, the irony): %s\n", err) |
| paddy@15 | 57 return |
| paddy@15 | 58 } |
| paddy@15 | 59 _, err = w.Write(d) |
| paddy@15 | 60 if err != nil { |
| paddy@15 | 61 log.Printf("Error writing json error: %s\n", err) |
| paddy@15 | 62 return |
| paddy@15 | 63 } |
| paddy@3 | 64 } |
| paddy@3 | 65 |
| paddy@17 | 66 func (c Context) RenderConfirmation(w io.Writer, r *http.Request, req AuthRequest) { |
| paddy@15 | 67 if c.Templates.Confirmation == nil { |
| paddy@15 | 68 log.Println("Confirmation template is nil, can't render confirmation.") |
| paddy@15 | 69 return |
| paddy@15 | 70 } |
| paddy@17 | 71 err := c.Templates.Confirmation.Execute(w, map[string]interface{}{ |
| paddy@17 | 72 "scope": req.Scope, |
| paddy@17 | 73 "client": req.Client, |
| paddy@17 | 74 "csrf_token": nosurf.Token(r), |
| paddy@17 | 75 }) |
| paddy@15 | 76 if err != nil { |
| paddy@15 | 77 log.Printf("Error executing confirmation template: %s\n", err) |
| paddy@15 | 78 return |
| paddy@15 | 79 } |
| paddy@1 | 80 } |
| paddy@1 | 81 |
| paddy@17 | 82 func (c Context) RenderLogin(w io.Writer, r *http.Request) { |
| paddy@15 | 83 if c.Templates.Login == nil { |
| paddy@15 | 84 log.Println("Login template is nil, can't render confirmation.") |
| paddy@15 | 85 return |
| paddy@15 | 86 } |
| paddy@17 | 87 err := c.Templates.Login.Execute(w, map[string]interface{}{ |
| paddy@17 | 88 "csrf_token": nosurf.Token(r), |
| paddy@17 | 89 }) |
| paddy@15 | 90 if err != nil { |
| paddy@15 | 91 log.Printf("Error executing login template: %s\n", err) |
| paddy@15 | 92 return |
| paddy@15 | 93 } |
| paddy@1 | 94 } |
| paddy@4 | 95 |
| paddy@4 | 96 func (c Context) RenderJSONToken(w io.Writer, data AccessData) { |
| paddy@15 | 97 d, err := json.Marshal(data) |
| paddy@15 | 98 if err != nil { |
| paddy@15 | 99 log.Printf("Error marshalling json token: %s\n", err) |
| paddy@15 | 100 return |
| paddy@15 | 101 } |
| paddy@15 | 102 _, err = w.Write(d) |
| paddy@15 | 103 if err != nil { |
| paddy@15 | 104 log.Printf("Error writing json token: %s\n", err) |
| paddy@15 | 105 return |
| paddy@15 | 106 } |
| paddy@4 | 107 } |