Implement password-based user interactive authentication.

This commit is contained in:
Jordan Bancino 2023-02-28 15:17:11 +00:00
parent e2806bc810
commit fae9eb4473
5 changed files with 64 additions and 26 deletions

View file

@ -13,9 +13,6 @@ Milestone: v0.2.0
[ ] Abstract /email/requestToken and /msidsn/requestToken [ ] Abstract /email/requestToken and /msidsn/requestToken
[x] Json API
[x] Trailing commas should not be allowed in arrays and objects
[x] Fix empty arrays not parsing
[~] Db API [~] Db API
[x] If object is in cache, but doesn't exist on disk, delete from cache [x] If object is in cache, but doesn't exist on disk, delete from cache
[ ] Allow cache to be totally disabled (no MIN_CACHE_SIZE) [ ] Allow cache to be totally disabled (no MIN_CACHE_SIZE)
@ -26,25 +23,13 @@ Milestone: v0.2.0
[x] Delete refresh token if present [x] Delete refresh token if present
[ ] Logout all [ ] Logout all
[ ] Login fallback (static HTML page) [ ] Login fallback (static HTML page)
[~] User Interactive [x] User Interactive
[ ] Passwords [x] Passwords
[ ] Registration tokens [x] Caller builds flows
[~] Caller builds flows
[ ] Document Uia (move docs from Matrix)
[x] Non-JSON endpoints
[x] Home page (like Synapse's "it works!")
[ ] Document new User functions [ ] Document new User functions
[ ] Document new JSON functions [ ] Document new JSON functions
[ ] Document Uia (move docs from Matrix)
[x] Refactor usage of StrDuplicate()
- Functions that keep strings do the duplication,
NOT their callers; callers free strings when they are
done with them.
[x] Remove HashMapGetKey() function
[x] HashMap
[x] JsonValueString()
[x] Db
Milestone: v0.3.0 Milestone: v0.3.0
----------------- -----------------
@ -55,10 +40,16 @@ Milestone: v0.3.0
[ ] Multi-output [ ] Multi-output
[ ] HTTP Client [ ] HTTP Client
[ ] Move configuration to database
- How is the initial configuration done?
[ ] /_telodendria/admin/config endpoint
[ ] Refactor TelodendriaConfig to just Config (ConfigLock() and ConfigUnlock())
[ ] Client-Server API [ ] Client-Server API
[ ] 4: Token-based user registration [ ] 4: Token-based user registration
[ ] Refactor user-interactive auth flow [ ] Implement user-interactive auth flow
[ ] Token validity endpoint [ ] Token validity endpoint
[ ] Add m.login.registration_token to registration endpoint flow
[ ] 4: Account management [ ] 4: Account management
[ ] Deactivate [ ] Deactivate
[ ] Change password [ ] Change password

View file

@ -112,7 +112,8 @@ ROUTE_IMPL(RouteRegister, args)
/* TODO: Add registration token flow */ /* TODO: Add registration token flow */
uiaResult = UiaComplete(uiaFlows, args->context, uiaResult = UiaComplete(uiaFlows, args->context,
args->matrixArgs->db, request, &response); args->matrixArgs->db, request, &response,
args->matrixArgs->config);
if (uiaResult < 0) if (uiaResult < 0)
{ {

View file

@ -31,6 +31,7 @@
#include <Str.h> #include <Str.h>
#include <Matrix.h> #include <Matrix.h>
#include <User.h>
struct UiaStage struct UiaStage
{ {
@ -201,7 +202,7 @@ UiaBuildStage(char *type, HashMap * params)
int int
UiaComplete(Array * flows, HttpServerContext * context, Db * db, UiaComplete(Array * flows, HttpServerContext * context, Db * db,
HashMap * request, HashMap ** response) HashMap * request, HashMap ** response, TelodendriaConfig * config)
{ {
JsonValue *val; JsonValue *val;
HashMap *auth; HashMap *auth;
@ -334,7 +335,52 @@ UiaComplete(Array * flows, HttpServerContext * context, Db * db,
} }
else if (strcmp(authType, "m.login.password") == 0) else if (strcmp(authType, "m.login.password") == 0)
{ {
/* TODO */ char *password = JsonValueAsString(HashMapGet(auth, "password"));
HashMap *identifier = JsonValueAsObject(HashMapGet(auth, "identifier"));
char *type;
UserId *userId;
User *user;
if (!password || !identifier)
{
HttpResponseStatus(context, HTTP_UNAUTHORIZED);
ret = BuildResponse(flows, db, response, session, dbRef);
goto finish;
}
type = JsonValueAsString(HashMapGet(identifier, "type"));
userId = UserParseId(JsonValueAsString(HashMapGet(identifier, "user")),
config->serverName);
if (!type || strcmp(type, "m.id.user") != 0
|| !userId || strcmp(userId->server, config->serverName) != 0)
{
HttpResponseStatus(context, HTTP_UNAUTHORIZED);
ret = BuildResponse(flows, db, response, session, dbRef);
UserFreeId(userId);
goto finish;
}
user = UserLock(db, userId->localpart);
if (!user)
{
HttpResponseStatus(context, HTTP_UNAUTHORIZED);
ret = BuildResponse(flows, db, response, session, dbRef);
UserFreeId(userId);
goto finish;
}
if (!UserCheckPassword(user, password))
{
HttpResponseStatus(context, HTTP_UNAUTHORIZED);
ret = BuildResponse(flows, db, response, session, dbRef);
UserFreeId(userId);
UserUnlock(user);
goto finish;
}
UserFreeId(userId);
UserUnlock(user);
} }
else if (strcmp(authType, "m.login.registration_token") == 0) else if (strcmp(authType, "m.login.registration_token") == 0)
{ {

View file

@ -657,8 +657,8 @@ finish:
return userId; return userId;
} }
void void
UserFreeId(UserId *id) UserFreeId(UserId * id)
{ {
if (id) if (id)
{ {

View file

@ -41,7 +41,7 @@ extern void
UiaCleanup(MatrixHttpHandlerArgs *); UiaCleanup(MatrixHttpHandlerArgs *);
extern int extern int
UiaComplete(Array *, HttpServerContext *, Db *, HashMap *, HashMap **); UiaComplete(Array *, HttpServerContext *, Db *, HashMap *, HashMap **, TelodendriaConfig *);
extern void extern void
UiaFlowsFree(Array *); UiaFlowsFree(Array *);