--------------------------------------------------------------------------------
-- SAML2 Middleware for WAI                                                   --
--------------------------------------------------------------------------------
-- This source code is licensed under the MIT license found in the LICENSE    --
-- file in the root directory of this source tree.                            --
--------------------------------------------------------------------------------

{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE LambdaCase #-}

-- | This modules defines the `NameIDFormat` type, which specifies the format
-- of name identifiers in an assertion.
--
-- @since 0.4
module Network.Wai.SAML2.NameIDFormat (
    NameIDFormat(..),
    parseNameIDFormat,
    showNameIDFormat
) where

--------------------------------------------------------------------------------

import GHC.Generics (Generic)

import Data.Text (Text, unpack)

--------------------------------------------------------------------------------

-- | Format of the subject identifier.
-- See 8.3 Name Identifier Format Identifiers in https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf
data NameIDFormat
    -- | The interpretation is left to individual implementations
    = Unspecified
    -- | @addr-spec@ as defined in IETF RFC 2822
    | EmailAddress
    -- | contents of the @<ds:X509SubjectName>@ element in the XML Signature Recommendation
    | X509SubjectName
    -- | String of the form @DomainName\UserName@
    | WindowsDomainQualifiedName
    -- | Kerberos principal name using the format @name[/instance]@REALM@
    | KerberosPrincipalName
    -- | identifier of an entity that provides SAML-based services
    -- (such as a SAML authority, requester, or responder) or is a participant in SAML profiles (such as a service
    -- provider supporting the browser SSO profile)
    | Entity
    -- | identifier of a provider of SAML-based services
    -- (such as a SAML authority) or a participant in SAML
    -- profiles (such as a service provider supporting the browser profiles)
    | Provider
    -- | persistent opaque identifier that corresponds to an identity
    -- federation between an identity provider and a service provider
    | Federated
    -- | an identifier with transient semantics and SHOULD be treated
    -- as an opaque and temporary value by the relying party
    | Transient
    -- | persistent opaque identifier for a principal that is specific to
    -- an identity provider and a service provider or affiliation of service providers
    | Persistent
    deriving (NameIDFormat -> NameIDFormat -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: NameIDFormat -> NameIDFormat -> Bool
$c/= :: NameIDFormat -> NameIDFormat -> Bool
== :: NameIDFormat -> NameIDFormat -> Bool
$c== :: NameIDFormat -> NameIDFormat -> Bool
Eq, Eq NameIDFormat
NameIDFormat -> NameIDFormat -> Bool
NameIDFormat -> NameIDFormat -> Ordering
NameIDFormat -> NameIDFormat -> NameIDFormat
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: NameIDFormat -> NameIDFormat -> NameIDFormat
$cmin :: NameIDFormat -> NameIDFormat -> NameIDFormat
max :: NameIDFormat -> NameIDFormat -> NameIDFormat
$cmax :: NameIDFormat -> NameIDFormat -> NameIDFormat
>= :: NameIDFormat -> NameIDFormat -> Bool
$c>= :: NameIDFormat -> NameIDFormat -> Bool
> :: NameIDFormat -> NameIDFormat -> Bool
$c> :: NameIDFormat -> NameIDFormat -> Bool
<= :: NameIDFormat -> NameIDFormat -> Bool
$c<= :: NameIDFormat -> NameIDFormat -> Bool
< :: NameIDFormat -> NameIDFormat -> Bool
$c< :: NameIDFormat -> NameIDFormat -> Bool
compare :: NameIDFormat -> NameIDFormat -> Ordering
$ccompare :: NameIDFormat -> NameIDFormat -> Ordering
Ord, Int -> NameIDFormat -> ShowS
[NameIDFormat] -> ShowS
NameIDFormat -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [NameIDFormat] -> ShowS
$cshowList :: [NameIDFormat] -> ShowS
show :: NameIDFormat -> String
$cshow :: NameIDFormat -> String
showsPrec :: Int -> NameIDFormat -> ShowS
$cshowsPrec :: Int -> NameIDFormat -> ShowS
Show, forall x. Rep NameIDFormat x -> NameIDFormat
forall x. NameIDFormat -> Rep NameIDFormat x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep NameIDFormat x -> NameIDFormat
$cfrom :: forall x. NameIDFormat -> Rep NameIDFormat x
Generic)

-- | Parse a 'NameIDFormat' (prefixed by @urn:oasis:names:tc:SAML:*:nameid-format@).
parseNameIDFormat :: MonadFail m => Text -> m NameIDFormat
parseNameIDFormat :: forall (m :: * -> *). MonadFail m => Text -> m NameIDFormat
parseNameIDFormat = \case
    Text
"urn:oasis:names:tc:SAML:1.1:nameid-format:Kerberos" -> forall (f :: * -> *) a. Applicative f => a -> f a
pure NameIDFormat
KerberosPrincipalName
    Text
"urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName" -> forall (f :: * -> *) a. Applicative f => a -> f a
pure NameIDFormat
WindowsDomainQualifiedName
    Text
"urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName" -> forall (f :: * -> *) a. Applicative f => a -> f a
pure NameIDFormat
X509SubjectName
    Text
"urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" -> forall (f :: * -> *) a. Applicative f => a -> f a
pure NameIDFormat
EmailAddress
    Text
"urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" -> forall (f :: * -> *) a. Applicative f => a -> f a
pure NameIDFormat
Unspecified
    Text
"urn:oasis:names:tc:SAML:2.0:nameid-format:entity" -> forall (f :: * -> *) a. Applicative f => a -> f a
pure NameIDFormat
Entity
    Text
"urn:oasis:names:tc:SAML:2.0:nameid-format:federated" -> forall (f :: * -> *) a. Applicative f => a -> f a
pure NameIDFormat
Federated
    Text
"urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" -> forall (f :: * -> *) a. Applicative f => a -> f a
pure NameIDFormat
Persistent
    Text
"urn:oasis:names:tc:SAML:2.0:nameid-format:provider" -> forall (f :: * -> *) a. Applicative f => a -> f a
pure NameIDFormat
Provider
    Text
"urn:oasis:names:tc:SAML:2.0:nameid-format:transient" -> forall (f :: * -> *) a. Applicative f => a -> f a
pure NameIDFormat
Transient
    Text
unknown -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall a b. (a -> b) -> a -> b
$ String
"parseNameIDFormat: unknown format " forall a. Semigroup a => a -> a -> a
<> Text -> String
unpack Text
unknown

-- | Displays a `NameIDFormat` value as a `Text` value.
showNameIDFormat :: NameIDFormat -> Text
showNameIDFormat :: NameIDFormat -> Text
showNameIDFormat = \case
    NameIDFormat
KerberosPrincipalName -> Text
"urn:oasis:names:tc:SAML:1.1:nameid-format:Kerberos"
    NameIDFormat
WindowsDomainQualifiedName -> Text
"urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName"
    NameIDFormat
X509SubjectName -> Text
"urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName"
    NameIDFormat
EmailAddress -> Text
"urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
    NameIDFormat
Unspecified -> Text
"urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
    NameIDFormat
Entity -> Text
"urn:oasis:names:tc:SAML:2.0:nameid-format:entity"
    NameIDFormat
Federated -> Text
"urn:oasis:names:tc:SAML:2.0:nameid-format:federated"
    NameIDFormat
Persistent -> Text
"urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"
    NameIDFormat
Provider -> Text
"urn:oasis:names:tc:SAML:2.0:nameid-format:provider"
    NameIDFormat
Transient -> Text
"urn:oasis:names:tc:SAML:2.0:nameid-format:transient"

--------------------------------------------------------------------------------