Skip to content

feat: implement passwordless flows (otp)#42

Merged
hozier merged 1 commit intomainfrom
p-william-hozier/passwordless-flows
May 16, 2025
Merged

feat: implement passwordless flows (otp)#42
hozier merged 1 commit intomainfrom
p-william-hozier/passwordless-flows

Conversation

@hozier
Copy link
Owner

@hozier hozier commented May 8, 2025

Issues worked on:

  • Passwordless authentication using One-Time Passwords (OTP) allows users to securely log in without remembering or transmitting passwords.

Copilot AI review requested due to automatic review settings May 8, 2025 22:55
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements passwordless authentication via OTP, enhancing security by enabling users to log in without traditional passwords. Key changes include:

  • Implementation of an OTP provider and its integration into the authentication flow.
  • Enhancements in secret management (addition of secret deletion) and adjustments to JWT configurations.
  • Updates to API definitions and documentation to support the new OTP endpoints.

Reviewed Changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/src/test/scala/com/theproductcollectiveco/play4s/auth/DefaultOtpProviderSpec.scala Added tests to validate OTP round-trip functionality.
app/src/main/scala/com/theproductcollectiveco/play4s/auth/DefaultOtpProvider.scala Implements OTP initialization and validation logic.
app/src/main/scala/com/theproductcollectiveco/play4s/auth/DefaultKeyStoreBackend.scala Introduces deletion functionality for stored secrets in the keystore.
app/src/main/scala/com/theproductcollectiveco/play4s/auth/DefaultJwtProvider.scala Adjusts JWT leeway and refines error handling using AuthProcessingError.
app/src/main/scala/com/theproductcollectiveco/play4s/auth/DefaultAuthProvider.scala Modifies secret initialization to accept an optional provided secret and adds secret removal.
app/src/main/scala/com/theproductcollectiveco/play4s/api/AuthService.scala Integrates OTP provider into the auth service with endpoints for OTP initiation and redemption.
app/src/main/scala/com/theproductcollectiveco/play4s/MainApp.scala Registers the new OTP provider within the main application.
api/src/main/smithy/com/theproductcollectiveco/play4s/internal/auth/service-auth-api.smithy Adds OTP-related operations and updates error definitions.
api/src/main/smithy/com/theproductcollectiveco/play4s/internal/auth/model.smithy Introduces the OTP and contact models required for OTP flows.
api/src/main/smithy/com/theproductcollectiveco/play4s/game/sudoku/errors.smithy Adds definitions for AuthValidationError and AuthProcessingError.
README.md Documents new endpoints for OTP initiation and authorization.
Comments suppressed due to low confidence (1)

app/src/main/scala/com/theproductcollectiveco/play4s/api/AuthService.scala:43

  • The ifM branches appear inverted: when OTP validation returns true (indicating a valid OTP), the current code raises an error. Consider swapping the branches so that a valid OTP results in calling requestToken(requester) and an invalid OTP raises an error.
otpProvider.validateOtp(requester, otp).ifM(InvalidInputError("Invalid OTP supplied").raiseError, requestToken(requester))

SecureRandom.javaSecuritySecureRandom[F].flatMap { security =>
given SecureRandom[F] = security
UUIDGen.fromSecureRandom.randomUUID.map(_.toString).flatMap { uuid =>
loaded.retrieve(alias).flatMap { case Some(_) | None => loaded.store(alias, providedSecret.getOrElse(uuid)) }
Copy link

Copilot AI May 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The pattern matching 'case Some(_) | None' covers all cases, which makes the match redundant. Consider removing the match and directly calling loaded.store, if overwriting the secret is the intended behavior.

Suggested change
loaded.retrieve(alias).flatMap { case Some(_) | None => loaded.store(alias, providedSecret.getOrElse(uuid)) }
loaded.store(alias, providedSecret.getOrElse(uuid))

Copilot uses AI. Check for mistakes.
@hozier hozier force-pushed the p-william-hozier/passwordless-flows branch 28 times, most recently from 0dbc6a1 to f685638 Compare May 14, 2025 00:49
@hozier hozier force-pushed the p-william-hozier/passwordless-flows branch from f685638 to 30c5634 Compare May 15, 2025 02:06
@hozier hozier force-pushed the p-william-hozier/passwordless-flows branch from 30c5634 to c41d91c Compare May 15, 2025 02:07
@hozier hozier merged commit 8dfd215 into main May 16, 2025
1 check passed
@hozier hozier deleted the p-william-hozier/passwordless-flows branch May 16, 2025 19:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants