packages feed

servant-auth-token-api 0.2.1.0 → 0.3.0.0

raw patch · 3 files changed

+179/−4 lines, 3 filesdep +raw-strings-qqPVP ok

version bump matches the API change (PVP)

Dependencies added: raw-strings-qq

API changes (from Hackage documentation)

+ Servant.API.Auth.Token: instance Servant.Docs.Internal.ToParam (Servant.API.QueryParam.QueryParam "codes-count" GHC.Types.Word)
+ Servant.API.Auth.Token: type AuthGetSingleUseCodes = "auth" :> ("codes" :> (Capture "user-id" UserId :> (QueryParam "codes-count" Word :> (TokenHeader' '["auth-single-codes"] :> Get '[JSON] (OnlyField "codes" [SingleUseCode])))))
+ Servant.API.Auth.Token: type AuthSigninGetCodeMethod = "auth" :> ("signin" :> (QueryParam "login" Login :> Get '[JSON] Unit))
+ Servant.API.Auth.Token: type AuthSigninPostCodeMethod = "auth" :> ("signin" :> (QueryParam "login" Login :> (QueryParam "code" SingleUseCode :> (QueryParam "expire" Seconds :> Post '[JSON] (OnlyField "token" SimpleToken)))))
+ Servant.API.Auth.Token: type SingleUseCode = Text
- Servant.API.Auth.Token: type AuthAPI = AuthSigninMethod :<|> (AuthTouchMethod :<|> (AuthTokenInfoMethod :<|> (AuthSignoutMethod :<|> (AuthSignupMethod :<|> (AuthUsersMethod :<|> (AuthGetUserMethod :<|> (AuthPatchUserMethod :<|> (AuthPutUserMethod :<|> (AuthDeleteUserMethod :<|> (AuthRestoreMethod :<|> (AuthGetGroupMethod :<|> (AuthPostGroupMethod :<|> (AuthPutGroupMethod :<|> (AuthPatchGroupMethod :<|> (AuthDeleteGroupMethod :<|> AuthGroupsMethod)))))))))))))))
+ Servant.API.Auth.Token: type AuthAPI = AuthSigninMethod :<|> (AuthSigninGetCodeMethod :<|> (AuthSigninPostCodeMethod :<|> (AuthTouchMethod :<|> (AuthTokenInfoMethod :<|> (AuthSignoutMethod :<|> (AuthSignupMethod :<|> (AuthUsersMethod :<|> (AuthGetUserMethod :<|> (AuthPatchUserMethod :<|> (AuthPutUserMethod :<|> (AuthDeleteUserMethod :<|> (AuthRestoreMethod :<|> (AuthGetSingleUseCodes :<|> (AuthGetGroupMethod :<|> (AuthPostGroupMethod :<|> (AuthPutGroupMethod :<|> (AuthPatchGroupMethod :<|> (AuthDeleteGroupMethod :<|> AuthGroupsMethod))))))))))))))))))

Files

CHANGELOG.md view
@@ -1,3 +1,8 @@+0.3.0.0+=======++* Add single use code authorisation.+ 0.2.1.0 ======= 
servant-auth-token-api.cabal view
@@ -1,5 +1,5 @@ name:                servant-auth-token-api-version:             0.2.1.0+version:             0.3.0.0 synopsis:            Servant based API for token based authorisation description:         Please see README.md homepage:            https://github.com/ncrashed/servant-auth-token-api#readme@@ -27,11 +27,13 @@     , aeson >= 0.11 && < 0.12     , aeson-injector >= 1.0.4 && < 1.1     , lens >= 4.13 && < 5+    , raw-strings-qq >= 1.1 && < 1.2     , servant >= 0.7 && < 0.9     , servant-docs >= 0.7 && < 0.9     , servant-swagger >= 1.0 && < 2     , swagger2 >= 2.0 && <= 3     , text >= 1.2 && < 2+       default-language:    Haskell2010   default-extensions:     DataKinds
src/Servant/API/Auth/Token.hs view
@@ -1,6 +1,10 @@-{-# LANGUAGE TemplateHaskell            #-} {-# LANGUAGE CPP #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE TemplateHaskell #-} {-# OPTIONS_GHC -fno-warn-orphans #-}+#if __GLASGOW_HASKELL__ >= 800+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}+#endif {-| Module      : Servant.API.Auth.Token Description : API for token based authorisation.@@ -14,6 +18,8 @@   -- * API specs     AuthAPI   , AuthSigninMethod+  , AuthSigninGetCodeMethod+  , AuthSigninPostCodeMethod   , AuthTouchMethod   , AuthTokenInfoMethod   , AuthSignoutMethod@@ -24,6 +30,7 @@   , AuthPutUserMethod   , AuthDeleteUserMethod   , AuthRestoreMethod+  , AuthGetSingleUseCodes   , AuthGetGroupMethod   , AuthPostGroupMethod   , AuthPutGroupMethod@@ -55,6 +62,7 @@   , Permission   , Seconds   , RestoreCode+  , SingleUseCode   , ReqRegister(..)   , RespUserInfo(..)   , PatchUser(..)@@ -88,6 +96,7 @@ import Servant.API import Servant.Docs  import Servant.Swagger+import Text.RawString.QQ  import Data.Text (Text) import qualified Data.Text as T @@ -167,6 +176,9 @@ type Seconds = Word -- | Special tag for password restore  type RestoreCode = Text +-- | Single use code used for authorisation via 'AuthSigninGetCodeMethod' and+-- 'AuthSigninPostCodeMethod' endpoints+type SingleUseCode = Text   -- | Token header that we require for authorization marked  -- by permissions that are expected from the token to pass guarding functions.@@ -371,6 +383,8 @@   toParam _ = DocQueryParam "expire" ["600", "30"] "Amount of time in seconds the returned token should be valid for, server can restrain maximum token life" Normal instance ToParam (QueryParam "code" RestoreCode) where   toParam _ = DocQueryParam "code" ["fdfygie", "sdf7230"] "Code that was sended to the user by some secure way" Normal+instance ToParam (QueryParam "codes-count" Word) where+  toParam _ = DocQueryParam "codes-count" ["1", "42"] "Count of single use codes to be generated by the server. Can be restricted with upper bound. If the parameter is missing, the server chooses a default value." Normal  instance ToCapture (Capture "user-id" UserId) where   toCapture _ = DocCapture "user-id" "unique identifier"@@ -380,6 +394,8 @@ -- | Generic authorization API type AuthAPI =        AuthSigninMethod+  :<|> AuthSigninGetCodeMethod+  :<|> AuthSigninPostCodeMethod   :<|> AuthTouchMethod   :<|> AuthTokenInfoMethod   :<|> AuthSignoutMethod@@ -390,6 +406,7 @@   :<|> AuthPutUserMethod   :<|> AuthDeleteUserMethod   :<|> AuthRestoreMethod+  :<|> AuthGetSingleUseCodes   :<|> AuthGetGroupMethod   :<|> AuthPostGroupMethod   :<|> AuthPutGroupMethod@@ -398,13 +415,84 @@   :<|> AuthGroupsMethod  -- | How to get a token, expire of 'Nothing' means --- some default value (server config)+-- some default value (server config).+--+-- Logic of authorisation via this method is:+--+-- * Client sends GET request to the endpoint with+-- user specified login and password and optional expire+--+-- * Server responds with token or error+--+-- * Client uses the token with other requests as authorisation+-- header+--+-- * Client can extend lifetime of token by periodically pinging+-- of 'AuthTouchMethod' endpoint+--+-- * Client can invalidate token instantly by 'AuthSignoutMethod'+--+-- * Client can get info about user with 'AuthTokenInfoMethod' endpoint. type AuthSigninMethod = "auth" :> "signin"   :> QueryParam "login" Login    :> QueryParam "password" Password    :> QueryParam "expire" Seconds   :> Get '[JSON] (OnlyField "token" SimpleToken) +-- | Authorisation via code of single usage.+--+-- Logic of authorisation via this method is:+-- +-- * Client sends GET request to 'AuthSigninGetCodeMethod' endpoint+--+-- * Server generates single use token and sends it via+--   SMS or email (server specific implementation)+--+-- * Client sends POST request to 'AuthSigninPostCodeMethod' endpoint+--+-- * Server responds with auth token.+--+-- * Client uses the token with other requests as authorisation+-- header+--+-- * Client can extend lifetime of token by periodically pinging+-- of 'AuthTouchMethod' endpoint+--+-- * Client can invalidate token instantly by 'AuthSignoutMethod'+--+-- * Client can get info about user with 'AuthTokenInfoMethod' endpoint.+type AuthSigninGetCodeMethod = "auth" :> "signin"+  :> QueryParam "login" Login +  :> Get '[JSON] Unit++-- | Authorisation via code of single usage.+--+-- Logic of authorisation via this method is:+-- +-- * Client sends GET request to 'AuthSigninGetCodeMethod' endpoint+--+-- * Server generates single use token and sends it via+--   SMS or email (server specific implementation)+--+-- * Client sends POST request to 'AuthSigninPostCodeMethod' endpoint+--+-- * Server responds with auth token.+--+-- * Client uses the token with other requests as authorisation+-- header+--+-- * Client can extend lifetime of token by periodically pinging+-- of 'AuthTouchMethod' endpoint+--+-- * Client can invalidate token instantly by 'AuthSignoutMethod'+--+-- * Client can get info about user with 'AuthTokenInfoMethod' endpoint.+type AuthSigninPostCodeMethod = "auth" :> "signin"+  :> QueryParam "login" Login +  :> QueryParam "code" SingleUseCode+  :> QueryParam "expire" Seconds+  :> Post '[JSON] (OnlyField "token" SimpleToken)+ -- | Client cat expand the token lifetime, no permissions are required type AuthTouchMethod = "auth" :> "touch"    :> QueryParam "expire" Seconds@@ -472,6 +560,24 @@   :> QueryParam "password" Password    :> Post '[JSON] Unit +-- | Generate single usage codes that user can write down and use later for emergency +-- authorisation.+--+-- 'Nothing' for "codes-count" parameter means some default value defined by server. Server+-- can restrict maximum count of such codes.+--+-- Server should invalidate previous codes on subsequent calls of the endpoint.+--+-- Special authorisation tag can be used to disable the feature, merely don't give+-- the tag to users and they won't be able to generate codes.+--+-- See also: 'AuthSigninPostCodeMethod' for utilisation of the codes.+type AuthGetSingleUseCodes = "auth" :> "codes"+  :> Capture "user-id" UserId+  :> QueryParam "codes-count" Word +  :> TokenHeader' '["auth-single-codes"]+  :> Get '[JSON] (OnlyField "codes" [SingleUseCode])+ -- | Getting info about user group, requires 'authInfoPerm' for token type AuthGetGroupMethod = "auth" :> "group"   :> Capture "group-id" UserGroupId@@ -549,7 +655,9 @@     , "Also the API provides a way to pack users in hierarchy of groups with attached permissions."     ]   extra = -       mkExtra (Proxy :: Proxy AuthSigninMethod) "How to get a token, missing expire means some default value (server config)"+       mkExtra' (Proxy :: Proxy AuthSigninMethod) ["How to get a token, missing expire means some default value (server config).", simpleAuthDescr]+    <> mkExtra' (Proxy :: Proxy AuthSigninGetCodeMethod) ["Authorisation via codes of single usage, that are sended to user via different channel of communication.", singleUseAuthDescr]+    <> mkExtra' (Proxy :: Proxy AuthSigninPostCodeMethod) ["Authorisation via codes of single usage, that are sended to user via different channel of communication.", singleUseAuthDescr]     <> mkExtra (Proxy :: Proxy AuthTouchMethod) "Client cat expand the token lifetime, no permissions are required"     <> mkExtra (Proxy :: Proxy AuthTokenInfoMethod) "Get client info that is binded to the token"     <> mkExtra (Proxy :: Proxy AuthSignoutMethod) "Close session, after call of the method the token in header is not valid."@@ -560,6 +668,7 @@     <> mkExtra (Proxy :: Proxy AuthPutUserMethod) "Replace user with the user in the body, requires 'authUpdatePerm' for token"     <> mkExtra (Proxy :: Proxy AuthDeleteUserMethod) "Delete user from DB, requires 'authDeletePerm' and will cause cascade deletion, that is your usually want"     <> mkExtra (Proxy :: Proxy AuthRestoreMethod) "Generate new password for user. There is two phases, first, the method is called without 'code' parameter. The system sends email with a restore code to user email or sms (its depends on server). After that a call of the method with the code is needed to change password."+    <> mkExtra (Proxy :: Proxy AuthGetSingleUseCodes) authGetSingleUseCodesDescr     <> mkExtra (Proxy :: Proxy AuthGetGroupMethod) "Getting info about user group, requires 'authInfoPerm' for token"     <> mkExtra (Proxy :: Proxy AuthPostGroupMethod) "Inserting new user group, requires 'authUpdatePerm' for token"     <> mkExtra (Proxy :: Proxy AuthPutGroupMethod) "Replace info about given user group, requires 'authUpdatePerm' for token"@@ -569,6 +678,65 @@    mkExtra p s = extraInfo p $       defAction & notes <>~ [ DocNote "Description" [s] ]+  mkExtra' p ss = extraInfo p $  +    defAction & notes <>~ [ DocNote "Description" ss ]++  simpleAuthDescr = [r|+    Logic of authorisation via login and password method is:++    * Client sends GET request to the endpoint with+    user specified login and password and optional expire+   +    * Server responds with token or error+   +    * Client uses the token with other requests as authorisation+    header+   +    * Client can extend lifetime of token by periodically pinging+    of 'AuthTouchMethod' endpoint+   +    * Client can invalidate token instantly by 'AuthSignoutMethod'+   +    * Client can get info about user with 'AuthTokenInfoMethod' endpoint.+    |]++  singleUseAuthDescr = [r|+    Logic of authorisation via single use code method is:+    +    * Client sends GET request to 'AuthSigninGetCodeMethod' endpoint+   +    * Server generates single use token and sends it via+      SMS or email (server specific implementation)+   +    * Client sends POST request to 'AuthSigninPostCodeMethod' endpoint+   +    * Server responds with auth token.+   +    * Client uses the token with other requests as authorisation+    header+   +    * Client can extend lifetime of token by periodically pinging+    of 'AuthTouchMethod' endpoint+   +    * Client can invalidate token instantly by 'AuthSignoutMethod'+   +    * Client can get info about user with 'AuthTokenInfoMethod' endpoint.+    |]++  authGetSingleUseCodesDescr = [r|+    Generate single usage codes that user can write down and use later for emergency +    authorisation.+   +    'Nothing' for "codes-count" parameter means some default value defined by server. Server+    can restrict maximum count of such codes.+   +    Server should invalidate previous codes on subsequent calls of the endpoint.+   +    Special authorisation tag can be used to disable the feature, merely don't give+    the tag to users and they won't be able to generate codes.+   +    See also: 'AuthSigninPostCodeMethod' for utilisation of the codes.+    |]  instance ToSample Word where    toSamples _ = samples [0, 4, 8, 15, 16, 23, 42]