0
0
mirror of https://github.com/vx3r/wg-gen-web.git synced 2024-12-18 00:13:23 +00:00
wg-gen-web/auth/oauth2oidc/oauth2oidc.go

101 lines
2.4 KiB
Go
Raw Normal View History

2020-04-28 11:11:49 +00:00
package oauth2oidc
import (
"context"
"fmt"
"github.com/coreos/go-oidc"
log "github.com/sirupsen/logrus"
2021-04-06 12:23:23 +00:00
"github.com/vx3r/wg-gen-web/model"
2020-04-28 11:11:49 +00:00
"golang.org/x/oauth2"
"os"
)
2020-06-10 07:52:44 +00:00
// Oauth2idc in order to implement interface, struct is required
2020-04-28 11:11:49 +00:00
type Oauth2idc struct{}
var (
oauth2Config *oauth2.Config
oidcProvider *oidc.Provider
oidcIDTokenVerifier *oidc.IDTokenVerifier
)
// Setup validate provider
func (o *Oauth2idc) Setup() error {
var err error
oidcProvider, err = oidc.NewProvider(context.TODO(), os.Getenv("OAUTH2_PROVIDER"))
if err != nil {
return err
}
oidcIDTokenVerifier = oidcProvider.Verifier(&oidc.Config{
ClientID: os.Getenv("OAUTH2_CLIENT_ID"),
})
oauth2Config = &oauth2.Config{
ClientID: os.Getenv("OAUTH2_CLIENT_ID"),
ClientSecret: os.Getenv("OAUTH2_CLIENT_SECRET"),
RedirectURL: os.Getenv("OAUTH2_REDIRECT_URL"),
Scopes: []string{oidc.ScopeOpenID, "profile", "email"},
Endpoint: oidcProvider.Endpoint(),
}
return nil
}
// CodeUrl get url to redirect client for auth
func (o *Oauth2idc) CodeUrl(state string) string {
return oauth2Config.AuthCodeURL(state)
}
// Exchange exchange code for Oauth2 token
func (o *Oauth2idc) Exchange(code string) (*oauth2.Token, error) {
oauth2Token, err := oauth2Config.Exchange(context.TODO(), code)
if err != nil {
return nil, err
}
return oauth2Token, nil
}
// UserInfo get token user
func (o *Oauth2idc) UserInfo(oauth2Token *oauth2.Token) (*model.User, error) {
rawIDToken, ok := oauth2Token.Extra("id_token").(string)
if !ok {
return nil, fmt.Errorf("no id_token field in oauth2 token")
}
iDToken, err := oidcIDTokenVerifier.Verify(context.TODO(), rawIDToken)
if err != nil {
return nil, err
}
userInfo, err := oidcProvider.UserInfo(context.TODO(), oauth2.StaticTokenSource(oauth2Token))
if err != nil {
return nil, err
}
// ID Token payload is just JSON
var claims map[string]interface{}
if err := userInfo.Claims(&claims); err != nil {
return nil, fmt.Errorf("failed to get id token claims: %s", err)
}
// get some infos about user
user := &model.User{}
user.Sub = userInfo.Subject
user.Email = userInfo.Email
user.Profile = userInfo.Profile
if v, found := claims["name"]; found && v != nil {
user.Name = v.(string)
} else {
log.Error("name not found in user info claims")
}
user.Issuer = iDToken.Issuer
user.IssuedAt = iDToken.IssuedAt
return user, nil
}