100 lines
2.9 KiB
Go
100 lines
2.9 KiB
Go
package provider
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"golang.org/x/oauth2"
|
|
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// GenericOAuth provider
|
|
type GenericOAuth struct {
|
|
AuthURL string `long:"auth-url" env:"AUTH_URL" description:"Auth/Login URL"`
|
|
TokenURL string `long:"token-url" env:"TOKEN_URL" description:"Token URL"`
|
|
UserURL string `long:"user-url" env:"USER_URL" description:"URL used to retrieve user info"`
|
|
ClientID string `long:"client-id" env:"CLIENT_ID" description:"Client ID"`
|
|
ClientSecret string `long:"client-secret" env:"CLIENT_SECRET" description:"Client Secret" json:"-"`
|
|
Scopes []string `long:"scope" env:"SCOPE" env-delim:"," default:"profile" default:"email" description:"Scopes"`
|
|
TokenStyle string `long:"token-style" env:"TOKEN_STYLE" default:"header" choice:"header" choice:"query" description:"How token is presented when querying the User URL"`
|
|
|
|
OAuthProvider
|
|
}
|
|
|
|
// Name returns the name of the provider
|
|
func (o *GenericOAuth) Name() string {
|
|
return "generic-oauth"
|
|
}
|
|
|
|
// Setup performs validation and setup
|
|
func (o *GenericOAuth) Setup(log *logrus.Logger) error {
|
|
// Check parmas
|
|
if o.AuthURL == "" || o.TokenURL == "" || o.UserURL == "" || o.ClientID == "" || o.ClientSecret == "" {
|
|
return errors.New("providers.generic-oauth.auth-url, providers.generic-oauth.token-url, providers.generic-oauth.user-url, providers.generic-oauth.client-id, providers.generic-oauth.client-secret must be set")
|
|
}
|
|
|
|
// Create oauth2 config
|
|
o.Config = &oauth2.Config{
|
|
ClientID: o.ClientID,
|
|
ClientSecret: o.ClientSecret,
|
|
Endpoint: oauth2.Endpoint{
|
|
AuthURL: o.AuthURL,
|
|
TokenURL: o.TokenURL,
|
|
},
|
|
Scopes: o.Scopes,
|
|
}
|
|
|
|
o.ctx = context.Background()
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetLoginURL provides the login url for the given redirect uri and state
|
|
func (o *GenericOAuth) GetLoginURL(redirectURI, state string) string {
|
|
return o.OAuthGetLoginURL(redirectURI, state)
|
|
}
|
|
|
|
// ExchangeCode exchanges the given redirect uri and code for a token
|
|
func (o *GenericOAuth) ExchangeCode(redirectURI, code string) (string, error) {
|
|
token, err := o.OAuthExchangeCode(redirectURI, code)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return token.AccessToken, nil
|
|
}
|
|
|
|
// GetUser uses the given token and returns a complete provider.User object
|
|
func (o *GenericOAuth) GetUser(token string) (User, Roles, error) {
|
|
var user User
|
|
var roles Roles
|
|
|
|
req, err := http.NewRequest("GET", o.UserURL, nil)
|
|
if err != nil {
|
|
return user, roles, err
|
|
}
|
|
|
|
if o.TokenStyle == "header" {
|
|
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token))
|
|
} else if o.TokenStyle == "query" {
|
|
q := req.URL.Query()
|
|
q.Add("access_token", token)
|
|
req.URL.RawQuery = q.Encode()
|
|
}
|
|
|
|
client := &http.Client{}
|
|
res, err := client.Do(req)
|
|
if err != nil {
|
|
return user, roles, err
|
|
}
|
|
|
|
defer res.Body.Close()
|
|
err = json.NewDecoder(res.Body).Decode(&user)
|
|
|
|
return user, roles, err
|
|
}
|