Files
saml-oidc-bridge/internal/oidc/client.go

76 lines
1.9 KiB
Go

package oidc
import (
"context"
"fmt"
"net/url"
gooidc "github.com/coreos/go-oidc/v3/oidc"
"golang.org/x/oauth2"
"shamilnunhuck/saml-oidc-bridge/internal/config"
)
type Client struct {
Verifier *gooidc.IDTokenVerifier
OAuth2 *oauth2.Config
}
func NewClient(cfg *config.Config) (*Client, error) {
ctx := context.Background()
provider, err := gooidc.NewProvider(ctx, cfg.OIDC.Issuer)
if err != nil {
return nil, err
}
verifier := provider.Verifier(&gooidc.Config{ClientID: cfg.OIDC.ClientID})
redirect := cfg.Server.ExternalURL + cfg.OIDC.RedirectPath
scopes := []string{"openid"}
scopes = append(scopes, cfg.OIDC.Scopes...)
oauth2cfg := &oauth2.Config{
ClientID: cfg.OIDC.ClientID,
ClientSecret: cfg.OIDC.ClientSecret,
Endpoint: provider.Endpoint(),
Scopes: scopes,
RedirectURL: redirect,
}
return &Client{Verifier: verifier, OAuth2: oauth2cfg}, nil
}
type Claims struct {
Subject string `json:"sub"`
Email string `json:"email"`
Name string `json:"name"`
Groups []string `json:"groups"`
DisplayName string `json:"display_name"`
EmailVerified bool `json:"email_verified"`
FamilyName string `json:"family_name"`
GivenName string `json:"given_name"`
PreferredUsername string `json:"preferred_username"`
}
func (c *Client) AuthCodeURL(state string, extra url.Values) string {
return c.OAuth2.AuthCodeURL(state)
}
func (c *Client) ExchangeAndVerify(ctx context.Context, code string) (*Claims, error) {
token, err := c.OAuth2.Exchange(ctx, code)
if err != nil {
return nil, err
}
rawID, ok := token.Extra("id_token").(string)
if !ok {
return nil, fmt.Errorf("no id_token in token response")
}
idt, err := c.Verifier.Verify(ctx, rawID)
if err != nil {
return nil, err
}
var cl Claims
if err := idt.Claims(&cl); err != nil {
return nil, err
}
return &cl, nil
}