Skip to content

Commit ae447b1

Browse files
battermannfisx
andauthored
2nd Auth Factor for "Create authentication token for SCIM service" and "login" API (#2124)
(types & swagger only, no implementation) Co-authored-by: fisx <[email protected]>
1 parent b435f30 commit ae447b1

File tree

37 files changed

+204
-45
lines changed

37 files changed

+204
-45
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This change requires an nginz upgrade to expose the newly added endpoint for sending a verification code.

changelog.d/1-api-changes/pr-2124

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
New endpoint (`POST /verification-code/send`) for generating and sending a verification code for 2nd factor authentication actions.

charts/nginz/values.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,10 @@ nginx_conf:
281281
- path: ~* ^/teams/([^/]*)/search$
282282
envs:
283283
- all
284+
- path: /verification-code/send
285+
envs:
286+
- all
287+
disable_zauth: true
284288
galley:
285289
- path: /conversations/code-check
286290
disable_zauth: true

deploy/services-demo/conf/nginz/nginx.conf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,11 @@ http {
219219
proxy_pass http://brig;
220220
}
221221

222+
location /verification-code/send {
223+
include common_response_no_zauth.conf;
224+
proxy_pass http://brig;
225+
}
226+
222227
## brig authenticated endpoints
223228

224229
location /self {

libs/api-bot/src/Network/Wire/Bot/Monad.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,7 @@ mkBot :: BotTag -> User -> PlainTextPassword -> BotNet Bot
689689
mkBot tag user pw = do
690690
log Info $ botLogFields (userId user) tag . msg (val "Login")
691691
let ident = fromMaybe (error "No email") (userEmail user)
692-
let cred = PasswordLogin (LoginByEmail ident) pw Nothing
692+
let cred = PasswordLogin (LoginByEmail ident) pw Nothing Nothing
693693
auth <- login cred >>= maybe (throwM LoginFailed) return
694694
aref <- nextAuthRefresh auth
695695
env <- BotNet ask

libs/wire-api/src/Wire/API/Routes/Public/Brig.hs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,14 @@ type UserAPI =
172172
:> ReqBody '[JSON] ListUsersQuery
173173
:> Post '[JSON] [UserProfile]
174174
)
175+
:<|> Named
176+
"send-verification-code"
177+
( Summary "Send a verification code to a given email address."
178+
:> "verification-code"
179+
:> "send"
180+
:> ReqBody '[JSON] SendVerificationCode
181+
:> MultiVerb 'POST '[JSON] '[RespondEmpty 200 "Verification code sent."] ()
182+
)
175183

176184
type SelfAPI =
177185
Named

libs/wire-api/src/Wire/API/User.hs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ module Wire.API.User
9797
modelUser,
9898
modelUserIdList,
9999
modelVerifyDelete,
100+
101+
-- * 2nd factor auth
102+
SndFactorPasswordChallengeAction (..),
103+
SendVerificationCode (..),
104+
TeamFeatureSndFPasswordChallengeNotImplemented (..),
100105
)
101106
where
102107

@@ -1151,3 +1156,38 @@ instance S.ToSchema ListUsersQuery where
11511156
& S.description ?~ "exactly one of qualified_ids or qualified_handles must be provided."
11521157
& S.properties .~ InsOrdHashMap.fromList [("qualified_ids", uids), ("qualified_handles", handles)]
11531158
& S.example ?~ toJSON (ListUsersByIds [Qualified (Id UUID.nil) (Domain "example.com")])
1159+
1160+
-----------------------------------------------------------------------------
1161+
-- SndFactorPasswordChallenge
1162+
1163+
-- | remove this type once we have an implementation in order to find all the places where we need to touch code.
1164+
data TeamFeatureSndFPasswordChallengeNotImplemented
1165+
= TeamFeatureSndFPasswordChallengeNotImplemented
1166+
1167+
data SndFactorPasswordChallengeAction = GenerateScimToken | Login
1168+
deriving stock (Eq, Show, Enum, Bounded, Generic)
1169+
deriving (Arbitrary) via (GenericUniform SndFactorPasswordChallengeAction)
1170+
deriving (FromJSON, ToJSON, S.ToSchema) via (Schema SndFactorPasswordChallengeAction)
1171+
1172+
instance ToSchema SndFactorPasswordChallengeAction where
1173+
schema =
1174+
enum @Text "SndFactorPasswordChallengeAction" $
1175+
mconcat
1176+
[ element "generate_scim_token" GenerateScimToken,
1177+
element "login" Login
1178+
]
1179+
1180+
data SendVerificationCode = SendVerificationCode
1181+
{ svcAction :: SndFactorPasswordChallengeAction,
1182+
svcEmail :: Email
1183+
}
1184+
deriving stock (Eq, Show, Generic)
1185+
deriving (Arbitrary) via (GenericUniform SendVerificationCode)
1186+
deriving (FromJSON, ToJSON, S.ToSchema) via Schema SendVerificationCode
1187+
1188+
instance ToSchema SendVerificationCode where
1189+
schema =
1190+
object "SendVerificationCode" $
1191+
SendVerificationCode
1192+
<$> svcAction .= field "action" schema
1193+
<*> svcEmail .= field "email" schema

libs/wire-api/src/Wire/API/User/Activation.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ newtype ActivationKey = ActivationKey
8080

8181
-- | A random code for use with an 'ActivationKey' that is usually transmitted
8282
-- out-of-band, e.g. via email or sms.
83+
-- FUTUREWORK(leif): rename to VerificationCode
8384
newtype ActivationCode = ActivationCode
8485
{fromActivationCode :: AsciiBase64Url}
8586
deriving stock (Eq, Show, Generic)

libs/wire-api/src/Wire/API/User/Auth.hs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,15 @@ import Data.Text.Lazy.Encoding (decodeUtf8, encodeUtf8)
6666
import Data.Time.Clock (UTCTime)
6767
import Imports
6868
import Wire.API.Arbitrary (Arbitrary (arbitrary), GenericUniform (..))
69+
import Wire.API.User.Activation
6970
import Wire.API.User.Identity (Email, Phone)
7071

7172
--------------------------------------------------------------------------------
7273
-- Login
7374

7475
-- | Different kinds of logins.
7576
data Login
76-
= PasswordLogin LoginId PlainTextPassword (Maybe CookieLabel)
77+
= PasswordLogin LoginId PlainTextPassword (Maybe CookieLabel) (Maybe ActivationCode)
7778
| SmsLogin Phone LoginCode (Maybe CookieLabel)
7879
deriving stock (Eq, Show, Generic)
7980
deriving (Arbitrary) via (GenericUniform Login)
@@ -103,11 +104,19 @@ modelLogin = Doc.defineModel "Login" $ do
103104
\to allow targeted revocation of all cookies granted to that \
104105
\specific client."
105106
Doc.optional
107+
Doc.property "verification_code" Doc.string' $ do
108+
Doc.description "The login verification code for 2nd factor authentication. Required only if SndFactorPasswordChallenge is enabled for the team/server."
109+
Doc.optional
106110

107111
instance ToJSON Login where
108112
toJSON (SmsLogin p c l) = object ["phone" .= p, "code" .= c, "label" .= l]
109-
toJSON (PasswordLogin login password label) =
110-
object ["password" .= password, "label" .= label, loginIdPair login]
113+
toJSON (PasswordLogin login password label mbCode) =
114+
object
115+
[ "password" .= password,
116+
"label" .= label,
117+
loginIdPair login,
118+
"verification_code" .= mbCode
119+
]
111120

112121
instance FromJSON Login where
113122
parseJSON = withObject "Login" $ \o -> do
@@ -117,10 +126,10 @@ instance FromJSON Login where
117126
SmsLogin <$> o .: "phone" <*> o .: "code" <*> o .:? "label"
118127
Just pw -> do
119128
loginId <- parseJSON (Object o)
120-
PasswordLogin loginId pw <$> o .:? "label"
129+
PasswordLogin loginId pw <$> (o .:? "label") <*> (o .:? "verification_code")
121130

122131
loginLabel :: Login -> Maybe CookieLabel
123-
loginLabel (PasswordLogin _ _ l) = l
132+
loginLabel (PasswordLogin _ _ l _) = l
124133
loginLabel (SmsLogin _ _ l) = l
125134

126135
--------------------------------------------------------------------------------

libs/wire-api/src/Wire/API/User/Scim.hs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ import Web.Scim.Schema.Schema (Schema (CustomSchema))
8383
import qualified Web.Scim.Schema.Schema as Scim
8484
import qualified Web.Scim.Schema.User as Scim
8585
import qualified Web.Scim.Schema.User as Scim.User
86+
import Wire.API.User.Activation
8687
import Wire.API.User.Identity (Email)
8788
import Wire.API.User.Profile as BT
8889
import qualified Wire.API.User.RichInfo as RI
@@ -365,22 +366,26 @@ data CreateScimToken = CreateScimToken
365366
{ -- | Token description (as memory aid for whoever is creating the token)
366367
createScimTokenDescr :: !Text,
367368
-- | User password, which we ask for because creating a token is a "powerful" operation
368-
createScimTokenPassword :: !(Maybe PlainTextPassword)
369+
createScimTokenPassword :: !(Maybe PlainTextPassword),
370+
-- | User code (sent by email), for 2nd factor to 'createScimTokenPassword'
371+
createScimTokenCode :: !(Maybe ActivationCode)
369372
}
370373
deriving (Eq, Show)
371374

372375
instance A.FromJSON CreateScimToken where
373376
parseJSON = A.withObject "CreateScimToken" $ \o -> do
374377
createScimTokenDescr <- o A..: "description"
375378
createScimTokenPassword <- o A..:? "password"
379+
createScimTokenCode <- o A..:? "code"
376380
pure CreateScimToken {..}
377381

378382
-- Used for integration tests
379383
instance A.ToJSON CreateScimToken where
380384
toJSON CreateScimToken {..} =
381385
A.object
382386
[ "description" A..= createScimTokenDescr,
383-
"password" A..= createScimTokenPassword
387+
"password" A..= createScimTokenPassword,
388+
"code" A..= createScimTokenCode
384389
]
385390

386391
-- | Type used for the response of 'APIScimTokenCreate'.
@@ -463,7 +468,8 @@ instance ToSchema CreateScimToken where
463468
& type_ .~ Just SwaggerObject
464469
& properties
465470
.~ [ ("description", textSchema),
466-
("password", textSchema)
471+
("password", textSchema),
472+
("code", textSchema)
467473
]
468474
& required .~ ["description"]
469475

0 commit comments

Comments
 (0)