Multiple provider support + OIDC provider

This commit is contained in:
Thom Seddon
2019-09-18 17:55:52 +01:00
parent 5dfd4f2878
commit 5a9c6adedf
16 changed files with 1043 additions and 278 deletions

View File

@ -2,13 +2,15 @@ package provider
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"net/url"
)
// Google provider
type Google struct {
ClientId string `long:"client-id" env:"CLIENT_ID" description:"Client ID"`
ClientID string `long:"client-id" env:"CLIENT_ID" description:"Client ID"`
ClientSecret string `long:"client-secret" env:"CLIENT_SECRET" description:"Client Secret" json:"-"`
Scope string
Prompt string `long:"prompt" env:"PROMPT" description:"Space separated list of OpenID prompt options"`
@ -18,15 +20,48 @@ type Google struct {
UserURL *url.URL
}
func (g *Google) GetLoginURL(redirectUri, state string) string {
// Name returns the name of the provider
func (g *Google) Name() string {
return "google"
}
// Setup performs validation and setup
func (g *Google) Setup() error {
if g.ClientID == "" || g.ClientSecret == "" {
return errors.New("providers.google.client-id, providers.google.client-secret must be set")
}
// Set static values
g.Scope = "https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email"
g.LoginURL = &url.URL{
Scheme: "https",
Host: "accounts.google.com",
Path: "/o/oauth2/auth",
}
g.TokenURL = &url.URL{
Scheme: "https",
Host: "www.googleapis.com",
Path: "/oauth2/v3/token",
}
g.UserURL = &url.URL{
Scheme: "https",
Host: "www.googleapis.com",
Path: "/oauth2/v2/userinfo",
}
return nil
}
// GetLoginURL provides the login url for the given redirect uri and state
func (g *Google) GetLoginURL(redirectURI, state string) string {
q := url.Values{}
q.Set("client_id", g.ClientId)
q.Set("client_id", g.ClientID)
q.Set("response_type", "code")
q.Set("scope", g.Scope)
if g.Prompt != "" {
q.Set("prompt", g.Prompt)
}
q.Set("redirect_uri", redirectUri)
q.Set("redirect_uri", redirectURI)
q.Set("state", state)
var u url.URL
@ -36,12 +71,13 @@ func (g *Google) GetLoginURL(redirectUri, state string) string {
return u.String()
}
func (g *Google) ExchangeCode(redirectUri, code string) (string, error) {
// ExchangeCode exchanges the given redirect uri and code for a token
func (g *Google) ExchangeCode(redirectURI, code string) (string, error) {
form := url.Values{}
form.Set("client_id", g.ClientId)
form.Set("client_id", g.ClientID)
form.Set("client_secret", g.ClientSecret)
form.Set("grant_type", "authorization_code")
form.Set("redirect_uri", redirectUri)
form.Set("redirect_uri", redirectURI)
form.Set("code", code)
res, err := http.PostForm(g.TokenURL.String(), form)
@ -49,13 +85,14 @@ func (g *Google) ExchangeCode(redirectUri, code string) (string, error) {
return "", err
}
var token Token
var token token
defer res.Body.Close()
err = json.NewDecoder(res.Body).Decode(&token)
return token.Token, err
}
// GetUser uses the given token and returns a complete provider.User object
func (g *Google) GetUser(token string) (User, error) {
var user User