Commit a741bb57 authored by Eric Chiang's avatar Eric Chiang

examples/app: add facilities for requesting groups

parent b02a3a31
......@@ -68,7 +68,7 @@ func (fi bindataFileInfo) Sys() interface{} {
return nil
}
var _dataIndexHtml = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x94\x52\xcd\x4e\xc3\x30\x0c\xbe\xef\x29\xac\x9c\xe0\x30\x7a\x47\x6d\x25\x40\xdc\x90\x26\xf1\x02\x53\x9a\x78\x6d\xb4\xfc\x4c\x89\x8b\x36\x4d\x7b\x77\xdc\x96\xae\x5b\x81\x09\x6e\xfe\x14\xfb\xfb\x89\x9d\x37\xe4\x6c\xb9\x00\xc8\xab\xa0\x0f\xe5\x82\x2b\xae\x37\x21\x3a\x90\x8a\x4c\xf0\x85\xc8\x6c\xa8\x8d\x17\x65\xff\xc4\x8f\x24\x2b\x8b\x23\xea\x70\x9c\x40\x07\x75\x09\x4f\x2d\x35\xe8\xc9\x28\x49\x08\x4c\xf6\x78\xd1\xd0\x49\x5d\x4d\x00\xdc\xa9\xe0\x9c\x5c\x26\xdc\xc9\xc8\x13\x1a\xac\x49\x04\x61\x03\xca\x1a\xa6\x59\x1a\x9d\xee\x2f\x25\x32\xd6\x98\x4b\xe6\xc6\xef\x5a\x02\x3a\xec\xb0\x10\x84\x7b\x12\xe0\xa5\xe3\x5a\xc5\x90\xd2\x7a\x60\x12\x50\xce\xa6\x19\x9d\xcd\x70\x3d\x44\x3b\x1e\xc1\x6c\xe0\x61\xb5\x7a\x86\xd3\x69\x6a\xbd\x54\x48\x6d\xe5\x0c\xf3\x7d\x48\xdb\x32\x7c\xeb\xbf\xa8\x8b\xea\x48\xc6\x1a\xa9\x10\xeb\xca\x4a\xbf\x15\x3d\x1b\xda\x84\xff\xa4\x1a\xe6\xbc\x1e\xc7\xf2\xac\x23\xe7\x05\x7d\x37\x37\x5b\x97\x92\xd6\x56\x52\x6d\x05\x38\xa4\x26\xe8\x42\xb0\x9f\x8e\x70\xd0\x7e\x09\x1a\x17\x3f\xd8\xb8\xfa\x33\xee\x39\x1b\x9a\x36\x3f\xed\xed\x56\x80\xd7\xbd\x6a\xa4\xaf\xb1\x57\x1a\x75\x47\xfb\xd7\xa1\xbe\xc2\xf8\x40\xb7\x02\x45\xac\xf9\x1e\x30\x8a\xbf\xa8\xbf\x8f\xcd\x00\xd9\xef\xd2\x79\x36\x9c\x7b\x9e\x0d\xf7\xff\x19\x00\x00\xff\xff\xaf\x0b\xca\x75\x07\x03\x00\x00")
var _dataIndexHtml = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x94\x93\xcf\x8a\xe3\x30\x0c\xc6\xef\x7d\x0a\xe1\x7b\x37\xf7\xc5\x29\xec\x0e\xbd\x0d\x14\xe6\x05\x8a\x63\xab\x89\xa9\xff\x61\x2b\x43\x4b\xe9\xbb\x8f\x53\x37\x61\x52\xd2\xa1\x73\x93\xd1\x27\x7d\x3f\x49\x98\x77\x64\xcd\x66\x05\xc0\x1b\xaf\xce\x43\x90\xc3\x83\x8f\x16\x84\x24\xed\x5d\xcd\x2a\xe3\x5b\xed\x58\x49\x0d\xd9\x30\x85\x00\xff\x7a\xea\xd0\x91\x96\x82\x10\x72\xd9\x5f\xae\x5d\xe8\x09\xe8\x1c\xb0\x66\x84\x27\x62\xe0\x84\xcd\xb1\x8c\x3e\xa5\xbd\x34\x3a\xcb\x19\x04\x23\x24\x76\xde\x28\x8c\x39\xe5\xad\x15\xeb\x84\x41\xc4\xdc\x46\x81\xd1\x89\xc0\x1f\xa0\x88\xd7\x5a\xa5\x6f\xee\x55\x58\x26\xd9\x9e\x28\x0a\x48\xd2\x07\x4c\xcf\x29\x70\x50\xed\x8b\xea\x45\x8a\xbb\x78\x4e\x70\xb9\x80\x3e\xc0\x9f\xdd\xee\x3f\x5c\xaf\x13\xc4\xcc\x36\xf5\x8d\xd5\xd9\xf8\x53\x98\x3e\x3f\xdf\x6f\x5b\x1c\x76\x64\x49\xc4\x16\xa9\x66\xfb\xc6\x08\x77\x64\xb7\x6e\x68\x12\xfe\xb2\x55\xa9\x73\x6a\x2c\xe3\xd5\xd0\x7c\xb3\x5a\x80\x7b\xb8\xa8\x14\xc6\x34\x42\x1e\x19\x58\xa4\xce\xab\x9a\x65\x9e\xa1\x61\xf1\x7e\xf3\x0a\x57\x0b\x18\xb3\x73\x66\xcd\x04\x34\x2d\x87\x37\x71\xb3\x54\xf9\x30\xc0\xf6\x24\x3b\xe1\x5a\xbc\x39\x8d\xbe\x23\xfe\x7c\xa8\xfb\x30\xce\xd3\x4f\x03\x45\x6c\xf3\xb5\x30\xb2\x57\xdc\x3f\x46\x31\x40\xf5\xdc\x9a\x57\xe5\x43\xf0\xaa\xfc\x90\xaf\x00\x00\x00\xff\xff\x9c\x89\xe2\x28\x29\x03\x00\x00")
func dataIndexHtmlBytes() ([]byte, error) {
return bindataRead(
......@@ -83,7 +83,7 @@ func dataIndexHtml() (*asset, error) {
return nil, err
}
info := bindataFileInfo{name: "data/index.html", size: 775, mode: os.FileMode(420), modTime: time.Unix(1466378108, 0)}
info := bindataFileInfo{name: "data/index.html", size: 809, mode: os.FileMode(436), modTime: time.Unix(1468620773, 0)}
a := &asset{bytes: bytes, info: info}
return a, nil
}
......
<html>
<body>
<form action="/login">
<table>
<tr>
<td> Authenticate for:
<br>
(comma-separated list of client-ids)
</td>
<td> <input type="text" name="cross_client" > </td>
</tr>
</table>
<p>
Authenticate for:<input type="text" name="cross_client" placeholder="comma-separated list of client-ids">
</p>
<p>
Extra scopes:<input type="text" name="extra_scopes" placeholder="comma-separated list of scopes">
</p>
{{ if .OOB }}
<input type="submit" value="Login" formtarget="_blank">
{{ else }}
......
......@@ -218,18 +218,25 @@ func handleLoginFunc(c *oidc.Client) http.HandlerFunc {
panic("unable to proceed")
}
xClient := r.Form.Get("cross_client")
if xClient != "" {
var scopes []string
q := u.Query()
if scope := q.Get("scope"); scope != "" {
scopes = strings.Split(scope, " ")
}
if xClient := r.Form.Get("cross_client"); xClient != "" {
xClients := strings.Split(xClient, ",")
for i, x := range xClients {
xClients[i] = scope.ScopeGoogleCrossClient + x
for _, x := range xClients {
scopes = append(scopes, scope.ScopeGoogleCrossClient+x)
}
q := u.Query()
scope := q.Get("scope")
scopes := strings.Split(scope, " ")
scopes = append(scopes, xClients...)
scope = strings.Join(scopes, " ")
q.Set("scope", scope)
}
if extraScopes := r.Form.Get("extra_scopes"); extraScopes != "" {
scopes = append(scopes, strings.Split(extraScopes, ",")...)
}
if scopes != nil {
q.Set("scope", strings.Join(scopes, " "))
u.RawQuery = q.Encode()
}
......@@ -292,57 +299,69 @@ func handleResendFunc(c *oidc.Client, issuerURL, resendURL, cbURL url.URL) http.
func handleCallbackFunc(c *oidc.Client) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
refreshToken := r.URL.Query().Get("refresh_token")
code := r.URL.Query().Get("code")
if code == "" {
phttp.WriteError(w, http.StatusBadRequest, "code query param must be set")
return
}
tokens, err := exchangeAuthCode(c, code)
oac, err := c.OAuthClient()
if err != nil {
phttp.WriteError(w, http.StatusBadRequest,
fmt.Sprintf("unable to verify auth code with issuer: %v", err))
phttp.WriteError(w, http.StatusBadRequest, fmt.Sprintf("unable to create OAuth2 client: %v", err))
return
}
tok, err := jose.ParseJWT(tokens.IDToken)
if err != nil {
phttp.WriteError(w, http.StatusBadRequest,
fmt.Sprintf("unable to parse JWT: %v", err))
var token oauth2.TokenResponse
switch {
case code != "":
if token, err = oac.RequestToken(oauth2.GrantTypeAuthCode, code); err != nil {
phttp.WriteError(w, http.StatusBadRequest, fmt.Sprintf("unable to verify auth code with issuer: %v", err))
return
}
case refreshToken != "":
if token, err = oac.RequestToken(oauth2.GrantTypeRefreshToken, refreshToken); err != nil {
phttp.WriteError(w, http.StatusBadRequest, fmt.Sprintf("unable to refresh token: %v", err))
return
}
if token.RefreshToken == "" {
token.RefreshToken = refreshToken
}
default:
phttp.WriteError(w, http.StatusBadRequest, "code query param must be set")
return
}
claims, err := tok.Claims()
tok, err := jose.ParseJWT(token.IDToken)
if err != nil {
phttp.WriteError(w, http.StatusBadRequest,
fmt.Sprintf("unable to construct claims: %v", err))
phttp.WriteError(w, http.StatusBadRequest, fmt.Sprintf("unable to parse JWT: %v", err))
return
}
claims := new(bytes.Buffer)
if err := json.Indent(claims, tok.Payload, "", " "); err != nil {
phttp.WriteError(w, http.StatusBadRequest, fmt.Sprintf("unable to construct claims: %v", err))
return
}
s := fmt.Sprintf(`
<html>
<head>
<style>
/* make pre wrap */
pre {
white-space: pre-wrap; /* css-3 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
word-wrap: break-word; /* Internet Explorer 5.5+ */
}
</style>
</head>
<body>
<p> Token: %v</p>
<p> Claims: %v </p>
<a href="/resend?jwt=%s">Resend Verification Email</a>
<p> Refresh Token: %v </p>
<p> Token: <pre><code>%v</code></pre></p>
<p> Claims: <pre><code>%v</code></pre></p>
<p> Refresh Token: <pre><code>%v</code></pre></p>
<p><a href="%s?refresh_token=%s">Redeem refresh token</a><p>
<p><a href="/resend?jwt=%s">Resend Verification Email</a></p>
</body>
</html>`, tok.Encode(), claims, tok.Encode(), tokens.RefreshToken)
</html>`, tok.Encode(), claims.String(), token.RefreshToken, r.URL.Path, token.RefreshToken, tok.Encode())
w.Write([]byte(s))
}
}
func exchangeAuthCode(c *oidc.Client, code string) (oauth2.TokenResponse, error) {
oac, err := c.OAuthClient()
if err != nil {
return oauth2.TokenResponse{}, err
}
t, err := oac.RequestToken(oauth2.GrantTypeAuthCode, code)
if err != nil {
return oauth2.TokenResponse{}, err
}
return t, nil
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment