You've already forked oauth2-proxy
mirror of
https://github.com/oauth2-proxy/oauth2-proxy.git
synced 2025-10-08 22:51:59 +02:00
* Add sensible logging flag to default setup for logger * Fix default value flag for sensitive logging * Remove sensitive logging changes * Add Cidaas provider * Update CHANGELOG.md * Add required groups scope to defaults * Fix tests * Remove if block with protected resource * Fix linting * Adjust provider sorting, fixes * Directly handle error return Co-authored-by: Jan Larwig <jan@larwig.com> * Use less deep nesting Co-authored-by: Jan Larwig <jan@larwig.com> * Directly handle returned error Co-authored-by: Jan Larwig <jan@larwig.com> * Pass provider options to Cidaas provider Co-authored-by: Jan Larwig <jan@larwig.com> * Add import for provider options * Fix tests * Fix linting * Add Cidaas doc page * Add Cidaas provider doc page to overview * Fix link in docs * Fix link in docs * Add link to Cidaas * fix provider order in docs and changelog position Signed-off-by: Jan Larwig <jan@larwig.com> --------- Signed-off-by: Jan Larwig <jan@larwig.com> Co-authored-by: Teko012 <112829523+Teko012@users.noreply.github.com> Co-authored-by: Jan Larwig <jan@larwig.com> Co-authored-by: Kevin Kreitner <kevinkreitner@gmail.com>
145 lines
3.8 KiB
Go
145 lines
3.8 KiB
Go
package providers
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/bitly/go-simplejson"
|
|
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
|
|
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
|
|
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger"
|
|
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/requests"
|
|
)
|
|
|
|
type GroupsClaimList []GroupClaimEntry
|
|
|
|
type GroupClaimEntry struct {
|
|
GroupID string `json:"groupId"`
|
|
Roles []string `json:"roles"`
|
|
}
|
|
|
|
// CIDAASProvider represents an CIDAAS based Identity Provider
|
|
type CIDAASProvider struct {
|
|
*OIDCProvider
|
|
}
|
|
|
|
var _ Provider = (*CIDAASProvider)(nil)
|
|
|
|
const (
|
|
CidaasProviderName = "CIDAAS"
|
|
CidaasGroupName = "cidaas"
|
|
CidaasDefaultScope = "openid email profile roles groups"
|
|
)
|
|
|
|
// NewCIDAASProvider initiates a new CIDAASProvider
|
|
func NewCIDAASProvider(p *ProviderData, opts options.Provider) *CIDAASProvider {
|
|
p.setProviderDefaults(providerDefaults{
|
|
name: CidaasProviderName,
|
|
scope: CidaasDefaultScope,
|
|
})
|
|
|
|
return &CIDAASProvider{
|
|
OIDCProvider: NewOIDCProvider(p, opts.OIDCConfig),
|
|
}
|
|
}
|
|
|
|
// RefreshSession uses the RefreshToken to fetch new Access and ID Tokens
|
|
func (p *CIDAASProvider) RefreshSession(ctx context.Context, s *sessions.SessionState) (bool, error) {
|
|
if s == nil || s.RefreshToken == "" {
|
|
return false, nil
|
|
}
|
|
|
|
if err := p.redeemRefreshToken(ctx, s); err != nil {
|
|
return false, fmt.Errorf("unable to redeem refresh token: %w", err)
|
|
}
|
|
|
|
if err := p.EnrichSession(ctx, s); err != nil {
|
|
return false, fmt.Errorf("unable to enrich session data after refresh: %w %v", err, s)
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
// EnrichSession data to add email an groups
|
|
func (p *CIDAASProvider) EnrichSession(ctx context.Context, s *sessions.SessionState) error {
|
|
if p.ProfileURL.String() == "" && s.Email == "" {
|
|
return errors.New("id_token did not contain an email and profileURL is not defined")
|
|
} else if p.ProfileURL.String() == "" {
|
|
return nil
|
|
}
|
|
|
|
// Try to get missing emails or groups from a profileURL
|
|
if err := p.enrichFromUserinfoEndpoint(ctx, s); err != nil {
|
|
logger.Errorf("Warning: Profile URL request failed: %s", err)
|
|
}
|
|
|
|
// If a mandatory email wasn't set, error at this point.
|
|
if s.Email == "" {
|
|
return errors.New("neither the id_token nor the profileURL set an email")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// enrichFromUserinfoEndpoint enriches a session's Email & Groups via the JSON response of
|
|
// an OIDC profile URL
|
|
func (p *CIDAASProvider) enrichFromUserinfoEndpoint(ctx context.Context, s *sessions.SessionState) error {
|
|
// profile url is userinfo url in case of Cidaas
|
|
respJSON, err := requests.New(p.ProfileURL.String()).
|
|
WithContext(ctx).
|
|
WithHeaders(makeOIDCHeader(s.AccessToken)).
|
|
Do().
|
|
UnmarshalSimpleJSON()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
email, err := respJSON.Get(p.EmailClaim).String()
|
|
if err == nil && s.Email == "" {
|
|
s.Email = email
|
|
}
|
|
|
|
groups, err := p.extractGroups(respJSON)
|
|
if err != nil {
|
|
return fmt.Errorf("extracting groups failed: %w", err)
|
|
}
|
|
|
|
s.Groups = groups
|
|
return nil
|
|
}
|
|
|
|
func (p *CIDAASProvider) extractGroups(respJSON *simplejson.Json) ([]string, error) {
|
|
rawGroupsClaim, err := respJSON.Get(p.GroupsClaim).MarshalJSON()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var groupsClaimList GroupsClaimList
|
|
err = json.Unmarshal(rawGroupsClaim, &groupsClaimList)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var groups []string
|
|
for _, group := range groupsClaimList {
|
|
for _, role := range group.Roles {
|
|
groups = append(groups, fmt.Sprintf("%s:%s", group.GroupID, role))
|
|
}
|
|
}
|
|
|
|
// Cidaas specific roles
|
|
if rolesVal, rolesClaimExists := respJSON.CheckGet("roles"); rolesClaimExists {
|
|
cidaasRoles, err := rolesVal.StringArray()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("unmarshal roles failed: %w", err)
|
|
}
|
|
|
|
for _, role := range cidaasRoles {
|
|
groups = append(groups, fmt.Sprintf("%s:%s", CidaasGroupName, role))
|
|
}
|
|
}
|
|
|
|
return groups, nil
|
|
}
|