Skip to content
This repository has been archived by the owner on Jan 24, 2019. It is now read-only.

Commit

Permalink
immediately redeem refresh token for provider==Google
Browse files Browse the repository at this point in the history
  • Loading branch information
jehiah committed Jun 23, 2015
1 parent ae2a1e5 commit 8d50b37
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 15 deletions.
9 changes: 8 additions & 1 deletion oauthproxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,13 @@ func (p *OauthProxy) ProcessCookie(rw http.ResponseWriter, req *http.Request) (e
} else if ok && p.CookieRefresh != time.Duration(0) {
refresh := timestamp.Add(p.CookieRefresh)
if refresh.Before(time.Now()) {
ok = p.Validator(email) && p.provider.ValidateToken(access_token)
log.Printf("refreshing %s old session for %s (refresh after %s)", time.Now().Sub(timestamp), email, p.CookieRefresh)
ok = p.Validator(email)
log.Printf("re-validating %s valid:%v", email, ok)
if ok {
ok = p.provider.ValidateToken(access_token)
log.Printf("re-validating access token. valid:%v", ok)
}
if ok {
p.SetCookie(rw, req, value)
}
Expand Down Expand Up @@ -432,6 +438,7 @@ func (p *OauthProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
http.Redirect(rw, req, redirect, 302)
return
} else {
log.Printf("validating: %s is unauthorized")
p.ErrorPage(rw, 403, "Permission Denied", "Invalid Account")
return
}
Expand Down
4 changes: 2 additions & 2 deletions options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,9 @@ func TestDefaultProviderApiSettings(t *testing.T) {
o := testOptions()
assert.Equal(t, nil, o.Validate())
p := o.provider.Data()
assert.Equal(t, "https://accounts.google.com/o/oauth2/auth",
assert.Equal(t, "https://accounts.google.com/o/oauth2/auth?access_type=offline",
p.LoginUrl.String())
assert.Equal(t, "https://accounts.google.com/o/oauth2/token",
assert.Equal(t, "https://www.googleapis.com/oauth2/v3/token",
p.RedeemUrl.String())
assert.Equal(t, "", p.ProfileUrl.String())
assert.Equal(t, "profile email", p.Scope)
Expand Down
101 changes: 98 additions & 3 deletions providers/google.go
Original file line number Diff line number Diff line change
@@ -1,28 +1,36 @@
package providers

import (
"bytes"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strings"
)

type GoogleProvider struct {
*ProviderData
RedeemRefreshUrl *url.URL
}

func NewGoogleProvider(p *ProviderData) *GoogleProvider {
p.ProviderName = "Google"
if p.LoginUrl.String() == "" {
p.LoginUrl = &url.URL{Scheme: "https",
Host: "accounts.google.com",
Path: "/o/oauth2/auth"}
Path: "/o/oauth2/auth",
// to get a refresh token. see https://developers.google.com/identity/protocols/OAuth2WebServer#offline
RawQuery: "access_type=offline",
}
}
if p.RedeemUrl.String() == "" {
p.RedeemUrl = &url.URL{Scheme: "https",
Host: "accounts.google.com",
Path: "/o/oauth2/token"}
Host: "www.googleapis.com",
Path: "/oauth2/v3/token"}
}
if p.ValidateUrl.String() == "" {
p.ValidateUrl = &url.URL{Scheme: "https",
Expand Down Expand Up @@ -76,3 +84,90 @@ func jwtDecodeSegment(seg string) ([]byte, error) {
func (p *GoogleProvider) ValidateToken(access_token string) bool {
return validateToken(p, access_token, nil)
}

func (p *GoogleProvider) Redeem(redirectUrl, code string) (body []byte, token string, err error) {
if code == "" {
err = errors.New("missing code")
return
}

params := url.Values{}
params.Add("redirect_uri", redirectUrl)
params.Add("client_id", p.ClientID)
params.Add("client_secret", p.ClientSecret)
params.Add("code", code)
params.Add("grant_type", "authorization_code")
var req *http.Request
req, err = http.NewRequest("POST", p.RedeemUrl.String(), bytes.NewBufferString(params.Encode()))
if err != nil {
return
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

resp, err := http.DefaultClient.Do(req)
if err != nil {
return
}
body, err = ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
return
}

if resp.StatusCode != 200 {
err = fmt.Errorf("got %d from %q %s", resp.StatusCode, p.RedeemUrl.String(), body)
return
}

var jsonResponse struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
}
err = json.Unmarshal(body, &jsonResponse)
if err != nil {
return
}

token, err = p.redeemRefreshToken(jsonResponse.RefreshToken)
return
}

func (p *GoogleProvider) redeemRefreshToken(refreshToken string) (token string, err error) {
// https://developers.google.com/identity/protocols/OAuth2WebServer#refresh
params := url.Values{}
params.Add("client_id", p.ClientID)
params.Add("client_secret", p.ClientSecret)
params.Add("refresh_token", refreshToken)
params.Add("grant_type", "refresh_token")
var req *http.Request
req, err = http.NewRequest("POST", p.RedeemUrl.String(), bytes.NewBufferString(params.Encode()))
if err != nil {
return
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

resp, err := http.DefaultClient.Do(req)
if err != nil {
return
}
var body []byte
body, err = ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
return
}

if resp.StatusCode != 200 {
err = fmt.Errorf("got %d from %q %s", resp.StatusCode, p.RedeemUrl.String(), body)
return
}

var jsonResponse struct {
AccessToken string `json:"access_token"`
}
err = json.Unmarshal(body, &jsonResponse)
if err != nil {
return
}
return jsonResponse.AccessToken, nil
}
4 changes: 2 additions & 2 deletions providers/google_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ func TestGoogleProviderDefaults(t *testing.T) {
p := newGoogleProvider()
assert.NotEqual(t, nil, p)
assert.Equal(t, "Google", p.Data().ProviderName)
assert.Equal(t, "https://accounts.google.com/o/oauth2/auth",
assert.Equal(t, "https://accounts.google.com/o/oauth2/auth?access_type=offline",
p.Data().LoginUrl.String())
assert.Equal(t, "https://accounts.google.com/o/oauth2/token",
assert.Equal(t, "https://www.googleapis.com/oauth2/v3/token",
p.Data().RedeemUrl.String())
assert.Equal(t, "https://www.googleapis.com/oauth2/v1/tokeninfo",
p.Data().ValidateUrl.String())
Expand Down
16 changes: 10 additions & 6 deletions providers/provider_default.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,19 @@ func (p *ProviderData) Redeem(redirectUrl, code string) (body []byte, token stri
return body, v.Get("access_token"), err
}

// GetLoginURL with typical oauth parameters
func (p *ProviderData) GetLoginURL(redirectURI, finalRedirect string) string {
params := url.Values{}
params.Add("redirect_uri", redirectURI)
params.Add("approval_prompt", "force")
var a url.URL
a = *p.LoginUrl
params, _ := url.ParseQuery(a.RawQuery)
params.Set("redirect_uri", redirectURI)
params.Set("approval_prompt", "force")
params.Add("scope", p.Scope)
params.Add("client_id", p.ClientID)
params.Add("response_type", "code")
params.Set("client_id", p.ClientID)
params.Set("response_type", "code")
if strings.HasPrefix(finalRedirect, "/") {
params.Add("state", finalRedirect)
}
return fmt.Sprintf("%s?%s", p.LoginUrl, params.Encode())
a.RawQuery = params.Encode()
return a.String()
}
1 change: 0 additions & 1 deletion validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ func newValidatorImpl(domains []string, usersFile string,
if allowAll {
valid = true
}
log.Printf("validating: is %s valid? %v", email, valid)
return valid
}
return validator
Expand Down

0 comments on commit 8d50b37

Please sign in to comment.