Applications OIDC
L’orchestrateur d’identité Maverics peut être utilisé en tant que fournisseur d’identité pour protéger les applications OIDC.
oidcProvider
doit être définie.Options de configuration
Name
name
est un identifiant unique pour l’application.
Type
type
représente le type d’application. Lors de la définition des applications OIDC, le type
doit être oidc
.
ID du client
clientID
est un identifiant unique utilisé par les applications clientes pour s’identifier.
Secret du client
clientSecret
est un secret utilisé pour authentifier les applications clientes. La valeur du
secret peut être stockée dans un fournisseur de secrets.
URL de redirection d’authentification
redirectURLs
constituent une liste des URL autorisées auxquels la réponse à une requête d’authentification
peut être envoyée.
URL de redirection de déconnexion
logoutRedirectURLs
constituent une liste des URL autorisées auxquelles la réponse à une requête de déconnexion
peut être envoyée.
Mappage des réclamations
claimsMapping
permet la mise en correspondance des attributs de la session d’un utilisateur avec des
réclamations standard sur le jeton d’identification. Les réclamations ajoutées au jeton d’identification sont déterminées par
la valeur du paramètre « scope query » envoyé dans la requête d’autorisation. Les champs d’application
pris en charge, en plus du champ d’application openid
requis, sont l’adresse électronique
, le profil
,
l’adresse
et le téléphone
. Le mappage des valeurs des réclamations à un champ d’application est répertorié dans le document
OpenID Connect Core 1.0, section 5.4.
Le renvoi d’un nonce fourni dans la requête d’autorisation par le biais d’une réclamation dans la réponse du jeton d’identification est également pris en charge.
Par exemple, si les champs d’application de l’e-mail
et du profil
sont demandés dans la requête d’autorisation, qu’Azure
est le fournisseur d’identité utilisé et que le mappage des réclamations contient des mappages vers des attributs Azure, alors les réclamations relatives à l’e-mail
et au profil
seront incluses dans la réponse IDtoken avec la valeur de l’attribut associé.
Attribute Providers
attrProviders
constituent une configuration facultative pour un système d’identité ou un magasin de données à partir duquel l’OIDCProvider peut récupérer des attributs supplémentaires utilisés dans claimsMapping
.
Connecteur
connecteur
est une référence au nom du connecteur défini qui sera utilisé en tant que fournisseur d’attributs.
Mappage des noms d’utilisateur
usernameMapping
définit l’attribut qui sera utilisé en tant que clé de recherche pour interroger les attributs de l’utilisateur.
Authentification
authentication
définit la manière dont les utilisateurs sont authentifiés pour cette application.
IDPs
idps
répertorie les fournisseurs d’identité utilisés pour authentifier l’utilisateur.
Extension de services IsAuthenticated
isAuthenticatedSE
est une extension de services optionnelle qui peut être utilisée pour modifier le
comportement par défaut qui détermine si un utilisateur est déjà authentifié. Cette extension
doit être utilisée avec authenticateSE
.
Extension de services Authenticate
authenticateSE
est une extension de services optionnelle utilisée pour contrôler la manière dont
l’authentification sera effectuée. Cette extension doit être utilisée avec isAuthenticatedSE
.
Backchannel
Extension de services Authenticate
backchannel.authenticateSE
est une extension de services facultative utilisée pour prendre le contrôle de
la manière dont l’authentification de l’utilisateur final sera effectuée pour les flux OIDC backchannel tels que Resource
Owner Password Credentials Grant.
Access Token
accessToken
définit la configuration du jeton d’accès OAuth.
Type
typecan
doit être défini sur jwt
(par défaut) ou opaque
.
Longueur
length
définit la longueur d’un jeton d’accès opaque
. La longueur peut être comprise entre
22 et 256 caractères. Si elle n’est pas définie, la longueur
par défaut est de 28 caractères.
Durée de vie en secondes
lifetimeSeconds
contrôle la durée de vie d’un jeton d’accès. Par défaut, les jetons d’accès
disposent d’une durée de vie d’une heure.
Jeton d’actualisation
refreshToken
définit la configuration du jeton d’actualisation OAuth. Les jetons d’actualisation
sont utilisés pour obtenir un nouveau jeton d’accès sans interaction de l’utilisateur.
Les jetons d’actualisation sont automatiquement remplacés à chaque actualisation des jetons d’accès. En d’autres termes, à chaque fois qu’un jeton d’actualisation est utilisé pour générer un nouveau jeton d’accès, un nouveau jeton d’actualisation est également renvoyé. Si un jeton d’actualisation précédemment émis est réutilisé en dehors d’une fenêtre admissible, le jeton d’actualisation actif sera invalidé.
Les jetons d’actualisation sont renouvelés afin de se protéger contre les attaques par rejeu de jetons d’actualisation et contre les jetons d’actualisation compromis en raison d’une durée de vie prolongée. Pour plus d’informations, veuillez vous référer au document OAuth Security Topics RFC
Autorisation d’accès hors ligne
allowOfflineAccess
définit si un client a la possibilité de demander des jetons d’actualisation.
Les jetons d’actualisation ne seront délivrés que si l’indicateur allowOfflineAccess
est défini sur « true »
et que la requête d’autorisation inclut le champ d’application offline_access
.
Longueur
longueur
peut être fixée entre 22 et 256 caractères pour définir la longueur d’un
jeton d’actualisation. Si elle n’est pas définie, la longueur
par défaut est de 28 caractères.
Utilisateurs autorisés
allowedAudiences
est une configuration facultative qui présente une liste des utilisateurs
autorisés à consommer des jetons d’accès. Lorsqu’un client adresse une requête au
terminal d’autorisation, il est possible d’inclure un paramètre de ressource
facultatif
indiquant le public cible du jeton. La valeur fournie dans le paramètre de ressource
doit figurer dans la liste des utilisateurs autorisés.
Cette configuration est utilisée lorsque les serveurs de ressources, tels que les API, procèdent à des autorisations par le biais du jeton d’accès. Pour plus d’informations, veuillez vous référer au document RFC 9068.
Extension de services BuildIDTokenClaims
Le buildIDTokenClaimsSE
est une extension de services optionnelle qui permet de personnaliser la façon
dont sont construites les réclamations dans le jeton d’identification.
Extension de services BuildAccessTokenClaims
L’extension de services optionnelle buildAccessTokenClaimsSE
permet de personnaliser la façon
dont sont construites les revendications dans le jeton d’accès.
Exemples
Exemple de configuration de base de l’application OIDC
apps:
- name: exampleOIDCApp
type: oidc
clientID: exampleClientID
clientSecret: <exampleClientSecret>
redirectURLs:
- https://app.enterprise.com/oidc
logoutRedirectURLs:
- https://app.enterprise.com/oidc/logout
attrProviders:
- connector: ldap
usernameMapping: okta.email
authentication:
idps:
- okta
claimsMapping:
email: ldap.mail
given_name: ldap.givenname
family_name: ldap.sn
Application OIDC avec extension de services
apps:
- name: exampleOIDCApp
type: oidc
clientID: exampleClientID
clientSecret: <exampleClientSecret>
redirectURLs:
- https://app.enterprise.com/oidc
authentication:
isAuthenticatedSE:
funcName: IsAuthenticated
file: /etc/maverics/extensions/auth.go
authenticateSE:
funcName: Authenticate
file: /etc/maverics/extensions/auth.go
backchannel:
authenticateSE:
funcName: BackchannelAuthenticate
file: /etc/maverics/extensions/auth.go
buildAccessTokenClaimsSE:
funcName: BuildAccessTokenClaims
file: /etc/maverics/extensions/auth.go
buildIDTokenClaimsSE:
funcName: BuildIDTokenClaims
file: /etc/maverics/extensions/auth.go
claimsMapping:
email: okta.email
/etc/maverics/extensions/auth.go
package main
import (
"net/http"
"errors"
"crypto/sha256"
"encoding/hex"
"github.com/strata-io/service-extension/orchestrator"
)
func IsAuthenticated(api orchestrator.Orchestrator, _ http.ResponseWriter, _ *http.Request) bool {
logger := api.Logger()
logger.Debug("se", "determining if user is authenticated")
session, err := api.Session()
if err != nil {
logger.Error("se", "unable to retrieve session", "error", err.Error())
return false
}
isOktaAuth, err := session.GetString("okta.authenticated")
if err != nil {
logger.Error("se", "unable to retrieve session value", "error", err.Error())
return false
}
if isOktaAuth == "true" {
return true
}
return false
}
func Authenticate(api orchestrator.Orchestrator, rw http.ResponseWriter, req *http.Request) {
logger := api.Logger()
logger.Debug("se", "authenticating user")
oktaIDP, err := api.IdentityProvider("okta")
if err != nil {
logger.Error(
"se", "failed to retrieve Okta IDP",
"error", err.Error(),
)
http.Error(
rw,
http.StatusText(http.StatusInternalServerError),
http.StatusInternalServerError,
)
return
}
oktaIDP.Login(rw, req)
}
func BackchannelAuthenticate(api orchestrator.Orchestrator, req *http.Request) error {
logger := api.Logger()
logger.Debug("se", "authenticating user in backchannel flow")
username := req.Form.Get("username")
password := req.Form.Get("password")
secrets, err := api.SecretProvider()
if err != nil {
logger.Error(
"se", "failed to retrieve secret provider",
"error", err.Error(),
)
return errors.New("failed to retrieve secret provider")
}
pwdHash := secrets.GetString(username)
if len(pwdHash) == 0 {
return errors.New("invalid user credentials")
}
hash := sha256.Sum256([]byte(password))
hashHex := hex.EncodeToString(hash[:])
if pwdHash != hashHex {
return errors.New("invalid user credentials")
}
return nil
}
func BuildAccessTokenClaims(api orchestrator.Orchestrator, _ *http.Request) (map[string]any, error) {
logger := api.Logger()
logger.Debug("se", "building access token claims")
session, err := api.Session()
if err != nil {
logger.Error("se", "unable to retrieve session", "error", err.Error())
return nil, err
}
roles, err := session.GetString("okta.roles")
return map[string]any{
"scope": roles,
}, err
}
func BuildIDTokenClaims(api orchestrator.Orchestrator, _ *http.Request) (map[string]any, error) {
logger := api.Logger()
logger.Debug("se", "building ID token claims")
session, err := api.Session()
if err != nil {
logger.Error("se", "unable to retrieve session", "error", err.Error())
return nil, err
}
groups, err := session.GetString("okta.groups")
return map[string]any{
"groups": groups,
}, err
}