aboutsummaryrefslogtreecommitdiff
path: root/Psso/Challenge
diff options
context:
space:
mode:
authorwinter Sparkles2026-08-08 23:01:51 +0100
committerwinter Sparkles2026-08-08 23:01:51 +0100
commitb422b6ded608807c7d3bb8b965b3797ca513610b (patch)
tree7925fa972efbfff2a9bf8648334d49e3fd6b5df1 /Psso/Challenge
parent880a274e1ecbed42c76d3dc4a81161b3ae372726 (diff)
implement a large chunk of the auth system itself :D
Diffstat (limited to 'Psso/Challenge')
-rw-r--r--Psso/Challenge/Password.php32
-rw-r--r--Psso/Challenge/Totp.php27
-rw-r--r--Psso/Challenge/Username.php16
3 files changed, 75 insertions, 0 deletions
diff --git a/Psso/Challenge/Password.php b/Psso/Challenge/Password.php
new file mode 100644
index 0000000..c20f5e2
--- /dev/null
+++ b/Psso/Challenge/Password.php
@@ -0,0 +1,32 @@
+<?php
+namespace Psso\Challenge;
+
+use Psso\{Challenge, ChallengeResult, Input, AuthProvider, AuthInterface};
+
+class Password extends Challenge {
+ public function getInputs(): array {
+ if (isset($this->context->user)) {
+ return [
+ new Input('password', Input::SECRET, 'challenge.input.password')
+ ];
+ }
+ return [
+ new Input('username', Input::TEXT, 'challenge.input.username'),
+ new Input('password', Input::SECRET, 'challenge.input.password'),
+ ];
+ }
+
+ public function validate(
+ AuthProvider $provider, array $inputData
+ ): ChallengeResult {
+ self::requireInterface($provider, AuthInterface\Password::class);
+ $successful = $provider->validatePassword(
+ $inputData['username'] ?? $this->context->user,
+ $inputData['password']
+ );
+ return new ChallengeResult(
+ self::class, $successful, $inputData['username'] ?? null,
+ $successful ? null : 'challenge.message.wrong-password'
+ );
+ }
+}
diff --git a/Psso/Challenge/Totp.php b/Psso/Challenge/Totp.php
new file mode 100644
index 0000000..4fd47f4
--- /dev/null
+++ b/Psso/Challenge/Totp.php
@@ -0,0 +1,27 @@
+<?php
+namespace Psso\Challenge;
+use Psso\{Challenge, AuthProvider, ChallengeResult, Context, Input, AuthInterface};
+
+class Totp extends Challenge {
+ public static function create(Context $context): static {
+ self::requireKnownUser($context);
+ return new self($context);
+ }
+
+ public function getInputs(): array {
+ return [new Input('otp', Input::NUMERIC, 'challenge.input.otp')];
+ }
+
+ public function validate(
+ AuthProvider $provider, array $inputData
+ ): ChallengeResult {
+ self::requireInterface($provider, AuthInterface\Totp::class);
+ $success = $provider->validateTotp(
+ $this->context->user, $inputData['otp']
+ );
+ return new ChallengeResult(
+ self::class, $success, null,
+ $success ? null : 'challenge.message.wrong-otp'
+ );
+ }
+}
diff --git a/Psso/Challenge/Username.php b/Psso/Challenge/Username.php
new file mode 100644
index 0000000..43de085
--- /dev/null
+++ b/Psso/Challenge/Username.php
@@ -0,0 +1,16 @@
+<?php
+namespace Psso\Challenge;
+use Psso\{Challenge, AuthProvider, ChallengeResult, Input};
+
+/** Just asks for a username and sets it in the context. Always succeeds. */
+class Username extends Challenge {
+ public function getInputs(): array {
+ return [new Input('user', Input::TEXT, 'challenge.input.username')];
+ }
+
+ public function validate(
+ AuthProvider $provider, array $inputData
+ ): ChallengeResult {
+ return new ChallengeResult(self::class, true, $inputData['user'], null);
+ }
+}