-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Microsoft Authentication API -- -- Bindings to the Microsoft Identity API / Active Directory (AD) for -- building applications that use either Authorization Code (User-facing) -- or (App-only) authorization flows. Helper functions are provided for -- building OAuth2 authentication flows and keep tokens transactionally -- secure and up to date. @package ms-auth @version 0.3.0.0 -- | Settings for using Azure Active Directory as OAuth identity provider -- -- Both Auth Code Grant (i.e. with browser client interaction) -- and App-only (i.e. Client Credentials) authentication flows -- are supported. The former is useful when a user needs to login and -- delegate some permissions to the application (i.e. accessing personal -- data), whereas the second is for server processes and automation -- accounts. module Network.OAuth2.Provider.AzureAD data AzureAD -- |
--   AZURE_CLIENT_ID
--   
envClientId :: MonadIO f => f ClientId -- |
--   AZURE_CLIENT_SECRET
--   
envClientSecret :: MonadIO f => f ClientSecret -- |
--   AZURE_TENANT_ID
--   
envTenantId :: MonadIO f => f Text -- | Azure OAuth application (i.e. with user consent screen) -- -- NB : scope offline_access is ALWAYS requested -- -- create app at https://go.microsoft.com/fwlink/?linkid=2083908 -- -- also be aware to find the right client id. see -- https://stackoverflow.com/a/70670961 -- -- Throws AzureADException if AZURE_CLIENT_ID and/or -- AZURE_CLIENT_SECRET credentials are not found in the -- environment azureADApp :: MonadIO m => Text -> [Scope] -> m (IdpApplication 'ClientCredentials AzureAD) -- | Configuration object of the OAuth2 application data OAuthCfg OAuthCfg :: Text -> [Scope] -> AuthorizeState -> URI -> OAuthCfg -- | application name [$sel:oacAppName:OAuthCfg] :: OAuthCfg -> Text -- | OAuth2 and OIDC scopes [$sel:oacScopes:OAuthCfg] :: OAuthCfg -> [Scope] -- | OAuth2 state (a random string, -- https://www.rfc-editor.org/rfc/rfc6749#section-10.12 ) [$sel:oacAuthState:OAuthCfg] :: OAuthCfg -> AuthorizeState -- | OAuth2 redirect URI [$sel:oacRedirectURI:OAuthCfg] :: OAuthCfg -> URI -- | -- https://learn.microsoft.com/en-us/azure/active-directory/develop/userinfo data AzureADUser -- | Azure OAuth application (i.e. with user consent screen) -- -- NB : scopes openid and offline_access are ALWAYS -- requested since the library assumes we have access to refresh tokens -- and ID tokens -- -- Reference on Microsoft Graph permissions : -- https://learn.microsoft.com/en-us/graph/permissions-reference -- -- create app at https://go.microsoft.com/fwlink/?linkid=2083908 -- -- also be aware to find the right client id. see -- https://stackoverflow.com/a/70670961 -- -- Throws AzureADException if AZURE_CLIENT_ID and/or -- AZURE_CLIENT_SECRET credentials are not found in the -- environment azureOAuthADApp :: MonadIO m => OAuthCfg -> m (IdpApplication 'AuthorizationCode AzureAD) data AzureADException AADNoEnvVar :: String -> AzureADException instance GHC.Show.Show Network.OAuth2.Provider.AzureAD.AzureAD instance GHC.Classes.Eq Network.OAuth2.Provider.AzureAD.AzureAD instance GHC.Show.Show Network.OAuth2.Provider.AzureAD.AzureADUser instance GHC.Classes.Ord Network.OAuth2.Provider.AzureAD.AzureADUser instance GHC.Classes.Eq Network.OAuth2.Provider.AzureAD.AzureADUser instance Data.Aeson.Types.FromJSON.FromJSON Network.OAuth2.Provider.AzureAD.AzureADUser instance GHC.Exception.Type.Exception Network.OAuth2.Provider.AzureAD.AzureADException instance GHC.Show.Show Network.OAuth2.Provider.AzureAD.AzureADException -- | MS Identity user session based on OAuth tokens -- -- The library supports the following authentication scenarios : -- -- -- -- and provides functions to keep tokens up to date in the background. module Network.OAuth2.Session -- | App has (at most) one token at a time type Token t = TVar (Maybe t) -- | Create an empty Token store newNoToken :: MonadIO m => m (Token t) -- | Delete the current token expireToken :: MonadIO m => Token t -> m () -- | Read the current value of the token readToken :: MonadIO m => Token t -> m (Maybe t) -- | Fetch an OAuth token and keep it updated. Should be called as a first -- thing in the app -- -- NB : forks a thread in the background -- -- -- https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow fetchUpdateToken :: MonadIO m => IdpApplication 'ClientCredentials AzureAD -> Token OAuth2Token -> Manager -> m () -- | DefaultAzureCredential mechanism as in the Python SDK -- https://pypi.org/project/azure-identity/ -- -- Order of authentication attempts: -- -- 1) token request with client secret -- -- 2) token request via managed identity (App Service and Azure -- Functions) -- https://learn.microsoft.com/en-us/azure/app-service/overview-managed-identity?tabs=portal%2Chttp#rest-endpoint-reference defaultAzureCredential :: MonadIO m => String -> String -> IdpApplication 'ClientCredentials AzureAD -> Token OAuth2Token -> Manager -> m () -- | Login endpoint -- -- see azureADApp loginEndpoint :: MonadIO m => IdpApplication 'AuthorizationCode AzureAD -> RoutePattern -> Scotty m () -- | The identity provider redirects the client to the reply -- endpoint as part of the OAuth flow : -- https://learn.microsoft.com/en-us/graph/auth-v2-user?view=graph-rest-1.0&tabs=http#authorization-response -- -- NB : forks a thread per logged in user to keep their tokens up to date replyEndpoint :: MonadIO m => IdpApplication 'AuthorizationCode AzureAD -> Tokens UserSub OAuth2Token -> Manager -> RoutePattern -> Scotty m () -- | transactional token store type Tokens uid t = TVar (TokensData uid t) -- | Create an empty Tokens object newTokens :: (MonadIO m, Ord uid) => m (Tokens uid t) -- | sub field data UserSub -- | Look up a user identifier and return their current token, if any lookupUser :: (MonadIO m, Ord uid) => Tokens uid t -> uid -> m (Maybe t) -- | Remove a user, i.e. they will have to authenticate once more expireUser :: (MonadIO m, Ord uid) => Tokens uid t -> uid -> m () -- | return a list representation of the Tokens object tokensToList :: MonadIO m => Tokens k a -> m [(k, a)] -- | Decode the App Service ID token header -- X-MS-TOKEN-AAD-ID-TOKEN, look its user up in the local token -- store, supply token t to continuation. If the user -- sub cannot be found in the token store the browser is -- redirected to the login URI. -- -- Special case of aadHeaderIdToken withAADUser :: MonadIO m => Tokens UserSub t -> Text -> (t -> Action m ()) -> Action m () type Scotty = ScottyT Text type Action = ActionT Text instance GHC.Classes.Eq Network.OAuth2.Session.OAuthSessionError instance (GHC.Show.Show uid, GHC.Show.Show t) => GHC.Show.Show (Network.OAuth2.Session.TokensData uid t) instance (GHC.Classes.Eq uid, GHC.Classes.Eq t) => GHC.Classes.Eq (Network.OAuth2.Session.TokensData uid t) instance GHC.Exception.Type.Exception Network.OAuth2.Session.OAuthSessionError instance GHC.Show.Show Network.OAuth2.Session.OAuthSessionError -- | Functions for implementing Azure AD-based authentication -- -- Both Auth Code Grant (i.e. with browser client interaction) -- and App-only (i.e. Client Credentials) authentication flows -- are supported. The former is useful when a user needs to login and -- delegate some permissions to the application (i.e. accessing personal -- data), whereas the second is for server processes and automation -- accounts. module MSAuth -- | Load, parse and apply a .env file -- -- NB : overwrites any preexisting env vars -- -- NB2 : if the .env file is not found the program continues -- (i.e. this function is a no-op in that case) applyDotEnv :: MonadIO m => Maybe FilePath -> m () -- | App has (at most) one token at a time type Token t = TVar (Maybe t) -- | Create an empty Token store newNoToken :: MonadIO m => m (Token t) -- | Delete the current token expireToken :: MonadIO m => Token t -> m () -- | Read the current value of the token readToken :: MonadIO m => Token t -> m (Maybe t) -- | Fetch an OAuth token and keep it updated. Should be called as a first -- thing in the app -- -- NB : forks a thread in the background -- -- -- https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow fetchUpdateToken :: MonadIO m => IdpApplication 'ClientCredentials AzureAD -> Token OAuth2Token -> Manager -> m () -- | DefaultAzureCredential mechanism as in the Python SDK -- https://pypi.org/project/azure-identity/ -- -- Order of authentication attempts: -- -- 1) token request with client secret -- -- 2) token request via managed identity (App Service and Azure -- Functions) -- https://learn.microsoft.com/en-us/azure/app-service/overview-managed-identity?tabs=portal%2Chttp#rest-endpoint-reference defaultAzureCredential :: MonadIO m => String -> String -> IdpApplication 'ClientCredentials AzureAD -> Token OAuth2Token -> Manager -> m () -- | Login endpoint -- -- see azureADApp loginEndpoint :: MonadIO m => IdpApplication 'AuthorizationCode AzureAD -> RoutePattern -> Scotty m () -- | The identity provider redirects the client to the reply -- endpoint as part of the OAuth flow : -- https://learn.microsoft.com/en-us/graph/auth-v2-user?view=graph-rest-1.0&tabs=http#authorization-response -- -- NB : forks a thread per logged in user to keep their tokens up to date replyEndpoint :: MonadIO m => IdpApplication 'AuthorizationCode AzureAD -> Tokens UserSub OAuth2Token -> Manager -> RoutePattern -> Scotty m () -- | transactional token store type Tokens uid t = TVar (TokensData uid t) -- | Create an empty Tokens object newTokens :: (MonadIO m, Ord uid) => m (Tokens uid t) -- | sub field data UserSub -- | Look up a user identifier and return their current token, if any lookupUser :: (MonadIO m, Ord uid) => Tokens uid t -> uid -> m (Maybe t) -- | Remove a user, i.e. they will have to authenticate once more expireUser :: (MonadIO m, Ord uid) => Tokens uid t -> uid -> m () -- | return a list representation of the Tokens object tokensToList :: MonadIO m => Tokens k a -> m [(k, a)] -- | Decode the App Service ID token header -- X-MS-TOKEN-AAD-ID-TOKEN, look its user up in the local token -- store, supply token t to continuation. If the user -- sub cannot be found in the token store the browser is -- redirected to the login URI. -- -- Special case of aadHeaderIdToken withAADUser :: MonadIO m => Tokens UserSub t -> Text -> (t -> Action m ()) -> Action m () type Scotty = ScottyT Text type Action = ActionT Text