Safe Haskell | Safe-Inferred |
---|---|
Language | Haskell2010 |
A yesod-auth plugin for per-tenant SSO via OpenID Connect, using Authorization Code flow (AKA server flow) with client_secret_post client authentication.
Reserves "ya-oidc-*" as session keys.
Referenced standards: * OIDC Core: https://openid.net/specs/openid-connect-core-1_0.html * RFC 6749, OAuth 2.0: https://tools.ietf.org/html/rfc6749 * RFC 6750, OAuth 2.0 Bearer Token Usage: https://tools.ietf.org/html/rfc6750
Synopsis
- oidcPluginName :: Text
- authOIDC :: forall site. YesodAuthOIDC site => AuthPlugin site
- newtype ClientId = ClientId {
- unClientId :: Text
- newtype ClientSecret = ClientSecret {}
- type UserInfo = Object
- data UserInfoPreference
- class YesodAuth site => YesodAuthOIDC site where
- enableLoginPage :: Bool
- onBadLoginHint :: MonadAuthHandler site m => m TypedContent
- getProviderConfig :: MonadAuthHandler site m => LoginHint -> m (Either Provider IssuerLocation, ClientId)
- onProviderConfigDiscovered :: MonadAuthHandler site m => Provider -> ClientId -> DiffTime -> m ()
- onBadCallbackRequest :: MonadAuthHandler site m => Maybe OAuthErrorResponse -> m a
- getClientSecret :: MonadAuthHandler site m => ClientId -> Configuration -> m ClientSecret
- getScopes :: MonadAuthHandler site m => ClientId -> Configuration -> m [ScopeValue]
- getUserInfoPreference :: MonadAuthHandler site m => LoginHint -> ClientId -> Configuration -> m UserInfoPreference
- onSuccessfulAuthentication :: MonadAuthHandler site m => LoginHint -> ClientId -> Provider -> Tokens Object -> Maybe UserInfo -> m Text
- onSessionExpiry :: HandlerFor site ()
- getHttpManagerForOidc :: MonadAuthHandler site m => m (Either MockOidcProvider Manager)
- data OAuthErrorResponse = OAuthErrorResponse {}
- oidcSessionExpiryMiddleware :: YesodAuthOIDC site => HandlerFor site a -> HandlerFor site a
- oidcLoginR :: AuthRoute
- oidcForwardR :: AuthRoute
- oidcCallbackR :: AuthRoute
- data Configuration = Configuration {
- issuer :: IssuerLocation
- authorizationEndpoint :: Text
- tokenEndpoint :: Text
- userinfoEndpoint :: Maybe Text
- revocationEndpoint :: Maybe Text
- jwksUri :: Text
- responseTypesSupported :: [Text]
- subjectTypesSupported :: [Text]
- idTokenSigningAlgValuesSupported :: [JwsAlgJson]
- scopesSupported :: Maybe [ScopeValue]
- tokenEndpointAuthMethodsSupported :: Maybe [Text]
- claimsSupported :: Maybe [Text]
- data Provider = Provider {
- configuration :: Configuration
- jwkSet :: [Jwk]
- type IssuerLocation = Text
- data Tokens a = Tokens {
- accessToken :: Text
- tokenType :: Text
- idToken :: IdTokenClaims a
- idTokenJwt :: Jwt
- expiresIn :: Maybe Integer
- refreshToken :: Maybe Text
- data IdTokenClaims a = IdTokenClaims {}
- data MockOidcProvider = MockOidcProvider {
- mopDiscover :: Text -> Provider
- mopGetValidTokens :: LoginHint -> CallbackInput -> SessionStore IO -> OIDC -> Tokens Object
- mopRequestUserInfo :: Request -> Tokens Object -> Maybe Object
- data SessionStore (m :: Type -> Type) = SessionStore {
- sessionStoreGenerate :: m ByteString
- sessionStoreSave :: State -> Nonce -> m ()
- sessionStoreGet :: State -> m (Maybe Nonce)
- sessionStoreDelete :: m ()
- data OIDC = OIDC {}
- data JwsAlgJson
- = JwsAlgJson { }
- | Unsupported Text
- data JwsAlg
- newtype Jwt = Jwt {
- unJwt :: ByteString
- newtype IntDate = IntDate POSIXTime
- data CallbackInput = CallbackInput {}
Documentation
oidcPluginName :: Text Source #
The name used to render this plugin's routes, "oidc".
authOIDC :: forall site. YesodAuthOIDC site => AuthPlugin site Source #
Add this value to your YesodAuth instance's authPlugins
list
newtype ClientSecret Source #
Instances
Show ClientSecret Source # | |
Defined in Yesod.Auth.OIDC showsPrec :: Int -> ClientSecret -> ShowS # show :: ClientSecret -> String # showList :: [ClientSecret] -> ShowS # |
type UserInfo = Object Source #
Response of call to the UserInfo Endpoint. This library does not currently support signed or encrypted responses to this particular request (unlike the ID Token response which must be signed). C.f. OIDC Core 5.3.2
data UserInfoPreference Source #
GetUserInfoIfAvailable | Always requests the userinfo, as long as the |
GetUserInfoOnlyToSatisfyRequestedScopes | (Default). Only requests the user info if a) it's available
and b) the token endpoint did not return all the scoped claims
requested (cf |
NeverGetUserInfo |
Instances
Show UserInfoPreference Source # | |
Defined in Yesod.Auth.OIDC showsPrec :: Int -> UserInfoPreference -> ShowS # show :: UserInfoPreference -> String # showList :: [UserInfoPreference] -> ShowS # | |
Eq UserInfoPreference Source # | |
Defined in Yesod.Auth.OIDC (==) :: UserInfoPreference -> UserInfoPreference -> Bool # (/=) :: UserInfoPreference -> UserInfoPreference -> Bool # |
class YesodAuth site => YesodAuthOIDC site where Source #
Write an instance of this class for your Yesod App
enableLoginPage :: Bool Source #
(Optional). If this is False, there will be no 'authpageoidclogin' with
its default form asking for an email. This can be used if you
consolidate your various yesod auth plugins into one login page
outside of this plugin. In that case, you would initialise OIDC
login by POSTing to oidcForwardR
with "email" and Yesod's
defaultCsrfParamName
from your own page. Defaut is True.
onBadLoginHint :: MonadAuthHandler site m => m TypedContent Source #
(Optional) A callback to your app in case oidcForwardR is
called without the login_hint query parameter. Default
implementation throws a BadLoginHint
exception.
getProviderConfig :: MonadAuthHandler site m => LoginHint -> m (Either Provider IssuerLocation, ClientId) Source #
Looks up configuration. If none can be found, you should handle the fallback / error call yourself. Returns the ClientID for the given identity provider, and either the provider configuration itself, or otherwise just the Issuer URI. If the latter, this library will use OIDC discovery to retrieve the configuration.
The Issuer URI should only consist of the scheme (which must be "https:") and fully qualified host name (e.g. example.com), with no path etc.
The full configuration could be hard-coded or the cached result
of a previous discovery. Cf onProviderConfigDiscovered
.
Note that the Provider
is both the configuration and the result of
retrieving the keyset from jwks_uri.
onProviderConfigDiscovered :: MonadAuthHandler site m => Provider -> ClientId -> DiffTime -> m () Source #
(Optional). If the tenant is configured via a discovery URL, this function will be called with the discovered result and that result's retrieved keyset. This can be used to cache the configuration for the given duration. Since the oidc-client library combines discovery with key retrieval, the given time is the minimum of the two remaining cache lifetimes returned by both http requests.
:: MonadAuthHandler site m | |
=> Maybe OAuthErrorResponse | The OAuth Error Response if present (See RFC6749 §5.2 and
OIDC §3.1.2.6). This will only be |
-> m a |
(Optional). Do something if the oidcCallbackR
was called with
incorrect parameters or the Identity Provider returned an
error. This could happen if the request is not legitimate or if
the identity provider doesn't provide the required state
or
code
query or post parameters.
Defaults to a simple page showing the error (sans the error_uri).
getClientSecret :: MonadAuthHandler site m => ClientId -> Configuration -> m ClientSecret Source #
The printable-ASCII client_secret which you've set up with the provider ahead of time (this library does not support the dynamic registration spec).
getScopes :: MonadAuthHandler site m => ClientId -> Configuration -> m [ScopeValue] Source #
(Optional). The scopes that you are requesting. The "openid" scope will always be included in the eventual request whether or not you specify it here. Defaults to ["email"].
getUserInfoPreference :: MonadAuthHandler site m => LoginHint -> ClientId -> Configuration -> m UserInfoPreference Source #
(Optional). Configure the behaviour of when to request user
information. The default behaviour is to only make this request
if it's necessary satisfy the scopes in getScopes
.
onSuccessfulAuthentication Source #
:: MonadAuthHandler site m | |
=> LoginHint |
|
-> ClientId | |
-> Provider | |
-> Tokens Object | The OIDC 'Token Response', including a fully validated ID
Token. The |
-> Maybe UserInfo | The response of the userinfo endpoint is given depending on
the |
-> m Text |
(Required). Should return a unique identifier for this user to use as the key in the yesod app's session backend. Sent after the user has successfully authenticated and right before telling Yesod that the user is authenticated. This function can still cancel authentication if it throws an error or short-circuits.
If you are using the underlying OAuth spec for non-OIDC reasons, you can do extra work here, such as storing the access and refresh tokens.
onSessionExpiry :: HandlerFor site () Source #
Defaults to clearing the credentials from the session and redirecting to the site's logoutDest (if not currently there already or out loginDest)
getHttpManagerForOidc :: MonadAuthHandler site m => m (Either MockOidcProvider Manager) Source #
Should return your app's HttpManager
or a mock for
testing. Allows high-level mocking of the 3 functions that use
the HttpManager (as opposed to a lower-level mock of the 3 HTTP
responses themselves).
data OAuthErrorResponse Source #
As defined in RFC6749 §5.2
Instances
Show OAuthErrorResponse Source # | |
Defined in Yesod.Auth.OIDC showsPrec :: Int -> OAuthErrorResponse -> ShowS # show :: OAuthErrorResponse -> String # showList :: [OAuthErrorResponse] -> ShowS # |
oidcSessionExpiryMiddleware :: YesodAuthOIDC site => HandlerFor site a -> HandlerFor site a Source #
Checks if the user has authenticated via `yesod-auth-oidc`. If
so, checks for the session expiry time as returned by the original
ID Token. If expired, it removes the sessionExpiryKey
from the
session, then calls onSessionExpired
. We can greatly improve this
by following the specs that can request re-authentication via the
OIDC-defined "prompt" parameter, but this is not implemented yet.
You should add this to your app's middleware. This library cannot include it automatically.
Routes
oidcLoginR :: AuthRoute Source #
Optional route that reads in the "login hint" (commonly an email
address). Your app can use this for its main login screen, or it
could have a separate login screen not managed by this plugin but
which redirects to oidcForwardR
with the login_hint when
appropriate.
authpageoidclogin
oidcForwardR :: AuthRoute Source #
This accepts an email
post param. Looks up or discovers
the OIDC provider associated with this login_hint, and redirects
the user to the provider's Authorization Endpoint.
authpageoidcforward
oidcCallbackR :: AuthRoute Source #
This route is given to the provider so that the provider can redirect the user here with the appropriate Authorisation Code, at which point the library continues the authentication process.
authpageoidccallback
Re-exported from oidc-client
data Configuration #
An OpenID Provider Configuration
Instances
FromJSON Configuration | |
Defined in Web.OIDC.Client.Discovery.Provider parseJSON :: Value -> Parser Configuration # parseJSONList :: Value -> Parser [Configuration] # | |
Show Configuration | |
Defined in Web.OIDC.Client.Discovery.Provider showsPrec :: Int -> Configuration -> ShowS # show :: Configuration -> String # showList :: [Configuration] -> ShowS # | |
Eq Configuration | |
Defined in Web.OIDC.Client.Discovery.Provider (==) :: Configuration -> Configuration -> Bool # (/=) :: Configuration -> Configuration -> Bool # |
An OpenID Provider information
Provider | |
|
type IssuerLocation = Text #
Tokens | |
|
Instances
data IdTokenClaims a #
Claims required for an ID Token, plus recommended claims (nonce) and other custom claims.
Instances
Exposed or re-exported for testing and mocking
data MockOidcProvider Source #
MockOidcProvider | |
|
data SessionStore (m :: Type -> Type) #
Manages state and nonce.
(Maybe OIDC
should have them)
SessionStore | |
|
This data type represents information needed in the OpenID flow.
data JwsAlgJson #
Instances
FromJSON JwsAlgJson | |
Defined in Web.OIDC.Client.Discovery.Provider parseJSON :: Value -> Parser JwsAlgJson # parseJSONList :: Value -> Parser [JwsAlgJson] # | |
Show JwsAlgJson | |
Defined in Web.OIDC.Client.Discovery.Provider showsPrec :: Int -> JwsAlgJson -> ShowS # show :: JwsAlgJson -> String # showList :: [JwsAlgJson] -> ShowS # | |
Eq JwsAlgJson | |
Defined in Web.OIDC.Client.Discovery.Provider (==) :: JwsAlgJson -> JwsAlgJson -> Bool # (/=) :: JwsAlgJson -> JwsAlgJson -> Bool # |
A subset of the signature algorithms from the JWA Spec.
An encoded JWT.
Jwt | |
|