-
Notifications
You must be signed in to change notification settings - Fork 17
/
challenge.go
134 lines (104 loc) · 3.07 KB
/
challenge.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Package for handling challenge requests from Hydra(https://github.com/ory/hydra).
package idp
import (
"encoding/gob"
jwt "github.com/dgrijalva/jwt-go"
// "github.com/gorilla/sessions"
hclient "github.com/ory/hydra/client"
"net/http"
"time"
)
const (
SessionCookieName = "challenge"
)
type Challenge struct {
// Parent IDP that got the challenge
idp *IDP
// Hydra's client
Client *hclient.Client
// Time of expiration
Expires time.Time
// Unique JWT id
JTI string
// Redirect URL
Redirect string
// Requested scopes
Scopes []string
// Set in the challenge endpoint, after authenticated.
User string
}
func init() {
// Gob is used by gorilla sessions
gob.Register(&Challenge{})
}
// Saves the Challenge to it's session store
func (c *Challenge) Save(w http.ResponseWriter, r *http.Request) error {
session, err := c.idp.config.ChallengeStore.New(r, SessionCookieName)
if err != nil {
return err
}
session.Options = c.idp.createChallengeCookieOptions
session.Values[SessionCookieName] = c
return c.idp.config.ChallengeStore.Save(r, w, session)
}
// Update the Challenge, e.g. add user representation
func (c *Challenge) Update(w http.ResponseWriter, r *http.Request) error {
session, err := c.idp.config.ChallengeStore.Get(r, SessionCookieName)
if err != nil {
return err
}
session.Options = c.idp.createChallengeCookieOptions
session.Values[SessionCookieName] = c
return c.idp.config.ChallengeStore.Save(r, w, session)
}
// Deletes the challenge from the store
func (c *Challenge) Delete(w http.ResponseWriter, r *http.Request) error {
session, err := c.idp.config.ChallengeStore.Get(r, SessionCookieName)
if err != nil {
return err
}
session.Options = c.idp.deleteChallengeCookieOptions
return c.idp.config.ChallengeStore.Save(r, w, session)
}
// User refused access to requested scopes, forward the desicion to Hydra via redirection.
func (c *Challenge) RefuseAccess(w http.ResponseWriter, r *http.Request) error {
err := c.Delete(w, r)
if err != nil {
return err
}
http.Redirect(w, r, c.Redirect+"&consent=false", http.StatusFound)
return nil
}
// User granted access to requested scopes, forward the desicion to Hydra via redirection.
func (c *Challenge) GrantAccessToAll(w http.ResponseWriter, r *http.Request) error {
now := time.Now()
token := jwt.New(jwt.SigningMethodRS256)
claims := token.Claims.(jwt.MapClaims)
claims["aud"] = c.Client.GetID()
claims["exp"] = now.Add(time.Minute * 4).Unix()
claims["iat"] = now.Unix()
claims["scp"] = c.Scopes
claims["jti"] = c.JTI
claims["sub"] = c.User
// Sign and get the complete encoded token as a string
key, err := c.idp.getConsentKey()
if err != nil {
return err
}
tokenString, err := token.SignedString(key)
if err != nil {
return err
}
// Delete the cookie
err = c.Delete(w, r)
if err != nil {
return err
}
// All this work might have taken too long (fetching key may be time consuming)
// so check token expiration
if c.Expires.Before(time.Now()) {
return ErrorChallengeExpired
}
http.Redirect(w, r, c.Redirect+"&consent="+tokenString, http.StatusFound)
return nil
}