Password login & registration Passkey login May not be functional yet
This commit is contained in:
parent
b84461d0e7
commit
a9af73b557
3 changed files with 159 additions and 80 deletions
|
@ -14,34 +14,42 @@ import (
|
|||
"git.mstar.dev/mstar/linstrom/storage-new/models"
|
||||
)
|
||||
|
||||
func (a *Authenticator) StartPasskeyLogin(username string) (*protocol.CredentialAssertion, error) {
|
||||
// Start the login process via passkey for a given username.
|
||||
// Returns the credential options the passkey needs to sign
|
||||
func (a *Authenticator) StartPasskeyLogin(
|
||||
username string,
|
||||
) (*protocol.CredentialAssertion, uint64, error) {
|
||||
if ok, err := a.canUsernameLogin(username); !ok {
|
||||
return nil, other.Error("auth", "user may not login", err)
|
||||
return nil, 0, other.Error("auth", "user may not login", err)
|
||||
}
|
||||
acc, err := dbgen.User.Where(dbgen.User.Username.Eq(username)).First()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, 0, other.Error("auth", "failed to acquire user for login", err)
|
||||
}
|
||||
wrappedAcc := fakeUser{acc}
|
||||
options, session, err := a.webauthn.BeginLogin(&wrappedAcc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, 0, other.Error("auth", "failed to initiate passkey login", err)
|
||||
}
|
||||
pkeySession := models.LoginProcessToken{
|
||||
User: *acc,
|
||||
UserId: acc.ID,
|
||||
ExpiresAt: time.Now().Add(time.Minute * 3),
|
||||
Token: string(other.Must(json.Marshal(session))),
|
||||
Name: "",
|
||||
}
|
||||
err = dbgen.LoginProcessToken.Clauses(clause.OnConflict{UpdateAll: true}).Create(&pkeySession)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, 0, other.Error("auth", "failed to create login process token", err)
|
||||
}
|
||||
return options, nil
|
||||
return options, pkeySession.ID, nil
|
||||
}
|
||||
|
||||
// Complete a passkey login request
|
||||
// Takes the username logging in as well as the raw request containing the passkey response
|
||||
func (a *Authenticator) CompletePasskeyLogin(
|
||||
username string,
|
||||
sessionId uint64,
|
||||
response *http.Request,
|
||||
) (accessToken string, err error) {
|
||||
// Get user in question
|
||||
|
@ -50,7 +58,7 @@ func (a *Authenticator) CompletePasskeyLogin(
|
|||
return "", other.Error("auth", "failed to get user for passkey login completion", err)
|
||||
}
|
||||
// Get latest login token data
|
||||
loginToken, err := dbgen.LoginProcessToken.Where(dbgen.LoginProcessToken.UserId.Eq(acc.ID)).
|
||||
loginToken, err := dbgen.LoginProcessToken.Where(dbgen.LoginProcessToken.ID.Eq(sessionId)).
|
||||
First()
|
||||
if err != nil {
|
||||
return "", other.Error(
|
||||
|
@ -70,18 +78,33 @@ func (a *Authenticator) CompletePasskeyLogin(
|
|||
}
|
||||
// Hand data to webauthn for completion
|
||||
newSession, err := a.webauthn.FinishLogin(&fakeUser{acc}, pkeySession, response)
|
||||
jsonSession, err := json.Marshal(newSession)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", other.Error("auth", "passkey completion failed", err)
|
||||
}
|
||||
jsonSessionId, err := json.Marshal(newSession.ID)
|
||||
if err != nil {
|
||||
return "", other.Error("auth", "failed to marshal session", err)
|
||||
}
|
||||
jsonSession, err := json.Marshal(newSession.ID)
|
||||
if err != nil {
|
||||
return "", other.Error("auth", "failed to marshal session", err)
|
||||
}
|
||||
// Update credentials
|
||||
_, err = dbgen.UserAuthMethod.Where(dbgen.UserAuthMethod.Token.Like("%"+string(jsonSession)+"%")).
|
||||
// WARN: I am not sure if this will work
|
||||
// Using the ID of the passkey session *should* be unique enough to identify the correct one
|
||||
// Of course, even then, there's still the problem of matching as
|
||||
// I can't yet guarantee that the parsed json content for the ID would be the same
|
||||
_, err = dbgen.UserAuthMethod.Where(dbgen.UserAuthMethod.Token.Like("%"+string(jsonSessionId)+"%")).
|
||||
Update(dbgen.UserAuthMethod.Token, jsonSession)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", other.Error("auth", "failed to update credentials", err)
|
||||
}
|
||||
// And delete the login token
|
||||
dbgen.LoginProcessToken.Where(dbgen.LoginProcessToken.UserId.Eq(acc.ID)).Delete(loginToken)
|
||||
_, err = dbgen.LoginProcessToken.Where(dbgen.LoginProcessToken.UserId.Eq(acc.ID)).
|
||||
Delete(loginToken)
|
||||
if err != nil {
|
||||
return "", other.Error("auth", "failed to delete login process", err)
|
||||
}
|
||||
dbAccessToken := models.AccessToken{
|
||||
User: *acc,
|
||||
UserId: acc.ID,
|
||||
|
@ -89,13 +112,16 @@ func (a *Authenticator) CompletePasskeyLogin(
|
|||
}
|
||||
err = dbgen.AccessToken.Omit(dbgen.AccessToken.Token).Create(&dbAccessToken)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", other.Error("auth", "failed to generate access token", err)
|
||||
}
|
||||
|
||||
return dbAccessToken.Token, nil
|
||||
}
|
||||
|
||||
func (a *Authenticator) StartPasskeyRegistration(username string) error {
|
||||
// Start the process of registrating a passkey to an account
|
||||
func (a *Authenticator) StartPasskeyRegistration(
|
||||
username string,
|
||||
) (*protocol.CredentialAssertion, error) {
|
||||
// p.l.Infof("begin registration")
|
||||
//
|
||||
// // can we actually do not use the username at all?
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue