109 lines
3.0 KiB
Go
109 lines
3.0 KiB
Go
|
package oidc
|
||
|
|
||
|
import (
|
||
|
"crypto/rsa"
|
||
|
"fmt"
|
||
|
|
||
|
"github.com/ory/fosite"
|
||
|
"github.com/ory/fosite/compose"
|
||
|
"github.com/ory/fosite/token/jwt"
|
||
|
"gopkg.in/square/go-jose.v2"
|
||
|
|
||
|
"github.com/authelia/authelia/internal/configuration/schema"
|
||
|
"github.com/authelia/authelia/internal/utils"
|
||
|
)
|
||
|
|
||
|
// OpenIDConnectProvider for OpenID Connect.
|
||
|
type OpenIDConnectProvider struct {
|
||
|
privateKeys map[string]*rsa.PrivateKey
|
||
|
|
||
|
Fosite fosite.OAuth2Provider
|
||
|
Store *OpenIDConnectStore
|
||
|
}
|
||
|
|
||
|
// NewOpenIDConnectProvider new-ups a OpenIDConnectProvider.
|
||
|
func NewOpenIDConnectProvider(configuration *schema.OpenIDConnectConfiguration) (provider OpenIDConnectProvider, err error) {
|
||
|
provider = OpenIDConnectProvider{
|
||
|
Fosite: nil,
|
||
|
}
|
||
|
|
||
|
if configuration == nil {
|
||
|
return provider, nil
|
||
|
}
|
||
|
|
||
|
provider.Store = NewOpenIDConnectStore(configuration)
|
||
|
|
||
|
composeConfiguration := new(compose.Config)
|
||
|
|
||
|
key, err := utils.ParseRsaPrivateKeyFromPemStr(configuration.IssuerPrivateKey)
|
||
|
if err != nil {
|
||
|
return provider, fmt.Errorf("unable to parse the private key of the OpenID issuer: %w", err)
|
||
|
}
|
||
|
|
||
|
provider.privateKeys = make(map[string]*rsa.PrivateKey)
|
||
|
provider.privateKeys["main-key"] = key
|
||
|
|
||
|
// TODO: Consider implementing RS512 as well.
|
||
|
jwtStrategy := &jwt.RS256JWTStrategy{PrivateKey: key}
|
||
|
|
||
|
strategy := &compose.CommonStrategy{
|
||
|
CoreStrategy: compose.NewOAuth2HMACStrategy(
|
||
|
composeConfiguration,
|
||
|
[]byte(utils.HashSHA256FromString(configuration.HMACSecret)),
|
||
|
nil,
|
||
|
),
|
||
|
OpenIDConnectTokenStrategy: compose.NewOpenIDConnectStrategy(
|
||
|
composeConfiguration,
|
||
|
provider.privateKeys["main-key"],
|
||
|
),
|
||
|
JWTStrategy: jwtStrategy,
|
||
|
}
|
||
|
|
||
|
provider.Fosite = compose.Compose(
|
||
|
composeConfiguration,
|
||
|
provider.Store,
|
||
|
strategy,
|
||
|
AutheliaHasher{},
|
||
|
|
||
|
/*
|
||
|
These are the OAuth2 and OpenIDConnect factories. Order is important (the OAuth2 factories at the top must
|
||
|
be before the OpenIDConnect factories) and taken directly from fosite.compose.ComposeAllEnabled. The
|
||
|
commented factories are not enabled as we don't yet use them but are still here for reference purposes.
|
||
|
*/
|
||
|
compose.OAuth2AuthorizeExplicitFactory,
|
||
|
compose.OAuth2AuthorizeImplicitFactory,
|
||
|
compose.OAuth2ClientCredentialsGrantFactory,
|
||
|
compose.OAuth2RefreshTokenGrantFactory,
|
||
|
compose.OAuth2ResourceOwnerPasswordCredentialsFactory,
|
||
|
// compose.RFC7523AssertionGrantFactory,
|
||
|
|
||
|
compose.OpenIDConnectExplicitFactory,
|
||
|
compose.OpenIDConnectImplicitFactory,
|
||
|
compose.OpenIDConnectHybridFactory,
|
||
|
compose.OpenIDConnectRefreshFactory,
|
||
|
|
||
|
compose.OAuth2TokenIntrospectionFactory,
|
||
|
compose.OAuth2TokenRevocationFactory,
|
||
|
|
||
|
// compose.OAuth2PKCEFactory,
|
||
|
)
|
||
|
|
||
|
return provider, nil
|
||
|
}
|
||
|
|
||
|
// GetKeySet returns the jose.JSONWebKeySet for the OpenIDConnectProvider.
|
||
|
func (p OpenIDConnectProvider) GetKeySet() (webKeySet jose.JSONWebKeySet) {
|
||
|
for keyID, key := range p.privateKeys {
|
||
|
webKey := jose.JSONWebKey{
|
||
|
Key: &key.PublicKey,
|
||
|
KeyID: keyID,
|
||
|
Algorithm: "RS256",
|
||
|
Use: "sig",
|
||
|
}
|
||
|
|
||
|
webKeySet.Keys = append(webKeySet.Keys, webKey)
|
||
|
}
|
||
|
|
||
|
return webKeySet
|
||
|
}
|