Create providers package with Google default
This commit is contained in:
parent
41044ecac0
commit
e2931da853
62
providers/google.go
Normal file
62
providers/google.go
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
package providers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/bitly/go-simplejson"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GoogleProvider struct {
|
||||||
|
*ProviderData
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGoogleProvider(p *ProviderData) *GoogleProvider {
|
||||||
|
if p.LoginUrl.String() == "" {
|
||||||
|
p.LoginUrl = &url.URL{Scheme: "https",
|
||||||
|
Host: "accounts.google.com",
|
||||||
|
Path: "/o/oauth2/auth"}
|
||||||
|
}
|
||||||
|
if p.RedeemUrl.String() == "" {
|
||||||
|
p.RedeemUrl = &url.URL{Scheme: "https",
|
||||||
|
Host: "accounts.google.com",
|
||||||
|
Path: "/o/oauth2/token"}
|
||||||
|
}
|
||||||
|
if p.Scope == "" {
|
||||||
|
p.Scope = "profile email"
|
||||||
|
}
|
||||||
|
return &GoogleProvider{ProviderData: p}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *GoogleProvider) GetEmailAddress(auth_response *simplejson.Json,
|
||||||
|
unused_access_token string) (string, error) {
|
||||||
|
idToken, err := auth_response.Get("id_token").String()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
// id_token is a base64 encode ID token payload
|
||||||
|
// https://developers.google.com/accounts/docs/OAuth2Login#obtainuserinfo
|
||||||
|
jwt := strings.Split(idToken, ".")
|
||||||
|
b, err := jwtDecodeSegment(jwt[1])
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
data, err := simplejson.NewJson(b)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
email, err := data.Get("email").String()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return email, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func jwtDecodeSegment(seg string) ([]byte, error) {
|
||||||
|
if l := len(seg) % 4; l > 0 {
|
||||||
|
seg += strings.Repeat("=", 4-l)
|
||||||
|
}
|
||||||
|
|
||||||
|
return base64.URLEncoding.DecodeString(seg)
|
||||||
|
}
|
94
providers/google_test.go
Normal file
94
providers/google_test.go
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
package providers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"github.com/bitly/go-simplejson"
|
||||||
|
"github.com/bmizerany/assert"
|
||||||
|
"net/url"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func newGoogleProvider() *GoogleProvider {
|
||||||
|
return NewGoogleProvider(
|
||||||
|
&ProviderData{
|
||||||
|
LoginUrl: &url.URL{},
|
||||||
|
RedeemUrl: &url.URL{},
|
||||||
|
ProfileUrl: &url.URL{},
|
||||||
|
Scope: ""})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGoogleProviderDefaults(t *testing.T) {
|
||||||
|
p := newGoogleProvider()
|
||||||
|
assert.NotEqual(t, nil, p)
|
||||||
|
assert.Equal(t, "https://accounts.google.com/o/oauth2/auth",
|
||||||
|
p.Data().LoginUrl.String())
|
||||||
|
assert.Equal(t, "https://accounts.google.com/o/oauth2/token",
|
||||||
|
p.Data().RedeemUrl.String())
|
||||||
|
assert.Equal(t, "", p.Data().ProfileUrl.String())
|
||||||
|
assert.Equal(t, "profile email", p.Data().Scope)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGoogleProviderOverrides(t *testing.T) {
|
||||||
|
p := NewGoogleProvider(
|
||||||
|
&ProviderData{
|
||||||
|
LoginUrl: &url.URL{
|
||||||
|
Scheme: "https",
|
||||||
|
Host: "example.com",
|
||||||
|
Path: "/oauth/auth"},
|
||||||
|
RedeemUrl: &url.URL{
|
||||||
|
Scheme: "https",
|
||||||
|
Host: "example.com",
|
||||||
|
Path: "/oauth/token"},
|
||||||
|
ProfileUrl: &url.URL{
|
||||||
|
Scheme: "https",
|
||||||
|
Host: "example.com",
|
||||||
|
Path: "/oauth/profile"},
|
||||||
|
Scope: "profile"})
|
||||||
|
assert.NotEqual(t, nil, p)
|
||||||
|
assert.Equal(t, "https://example.com/oauth/auth",
|
||||||
|
p.Data().LoginUrl.String())
|
||||||
|
assert.Equal(t, "https://example.com/oauth/token",
|
||||||
|
p.Data().RedeemUrl.String())
|
||||||
|
assert.Equal(t, "https://example.com/oauth/profile",
|
||||||
|
p.Data().ProfileUrl.String())
|
||||||
|
assert.Equal(t, "profile", p.Data().Scope)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGoogleProviderGetEmailAddress(t *testing.T) {
|
||||||
|
p := newGoogleProvider()
|
||||||
|
j := simplejson.New()
|
||||||
|
j.Set("id_token", "ignored prefix."+base64.URLEncoding.EncodeToString(
|
||||||
|
[]byte("{\"email\": \"michael.bland@gsa.gov\"}")))
|
||||||
|
email, err := p.GetEmailAddress(j, "ignored access_token")
|
||||||
|
assert.Equal(t, "michael.bland@gsa.gov", email)
|
||||||
|
assert.Equal(t, nil, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGoogleProviderGetEmailAddressInvalidEncoding(t *testing.T) {
|
||||||
|
p := newGoogleProvider()
|
||||||
|
j := simplejson.New()
|
||||||
|
j.Set("id_token", "ignored prefix.{\"email\": \"michael.bland@gsa.gov\"}")
|
||||||
|
email, err := p.GetEmailAddress(j, "ignored access_token")
|
||||||
|
assert.Equal(t, "", email)
|
||||||
|
assert.NotEqual(t, nil, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGoogleProviderGetEmailAddressInvalidJson(t *testing.T) {
|
||||||
|
p := newGoogleProvider()
|
||||||
|
j := simplejson.New()
|
||||||
|
j.Set("id_token", "ignored prefix."+base64.URLEncoding.EncodeToString(
|
||||||
|
[]byte("{email: michael.bland@gsa.gov}")))
|
||||||
|
email, err := p.GetEmailAddress(j, "ignored access_token")
|
||||||
|
assert.Equal(t, "", email)
|
||||||
|
assert.NotEqual(t, nil, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGoogleProviderGetEmailAddressEmailMissing(t *testing.T) {
|
||||||
|
p := newGoogleProvider()
|
||||||
|
j := simplejson.New()
|
||||||
|
j.Set("id_token", "ignored prefix."+base64.URLEncoding.EncodeToString(
|
||||||
|
[]byte("{\"not_email\": \"missing!\"}")))
|
||||||
|
email, err := p.GetEmailAddress(j, "ignored access_token")
|
||||||
|
assert.Equal(t, "", email)
|
||||||
|
assert.NotEqual(t, nil, err)
|
||||||
|
}
|
14
providers/provider_data.go
Normal file
14
providers/provider_data.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package providers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ProviderData struct {
|
||||||
|
LoginUrl *url.URL
|
||||||
|
RedeemUrl *url.URL
|
||||||
|
ProfileUrl *url.URL
|
||||||
|
Scope string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ProviderData) Data() *ProviderData { return p }
|
18
providers/providers.go
Normal file
18
providers/providers.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package providers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/bitly/go-simplejson"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Provider interface {
|
||||||
|
Data() *ProviderData
|
||||||
|
GetEmailAddress(auth_response *simplejson.Json,
|
||||||
|
access_token string) (string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(provider string, p *ProviderData) Provider {
|
||||||
|
switch provider {
|
||||||
|
default:
|
||||||
|
return NewGoogleProvider(p)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user