diff --git a/docs/src/main/asciidoc/images/webauthn-custom-login.svg b/docs/src/main/asciidoc/images/webauthn-custom-login.svg
index e08ba0cd89ee0..ed2d6dee9c081 100644
--- a/docs/src/main/asciidoc/images/webauthn-custom-login.svg
+++ b/docs/src/main/asciidoc/images/webauthn-custom-login.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/main/asciidoc/images/webauthn-custom-register.svg b/docs/src/main/asciidoc/images/webauthn-custom-register.svg
index 75b98727ac93b..04628daff7c18 100644
--- a/docs/src/main/asciidoc/images/webauthn-custom-register.svg
+++ b/docs/src/main/asciidoc/images/webauthn-custom-register.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/main/asciidoc/images/webauthn-login.svg b/docs/src/main/asciidoc/images/webauthn-login.svg
index 0055a442c28e9..eaff8b619a2d7 100644
--- a/docs/src/main/asciidoc/images/webauthn-login.svg
+++ b/docs/src/main/asciidoc/images/webauthn-login.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/main/asciidoc/images/webauthn-register.svg b/docs/src/main/asciidoc/images/webauthn-register.svg
index 5c60cdb486b8e..7b6405aa86da0 100644
--- a/docs/src/main/asciidoc/images/webauthn-register.svg
+++ b/docs/src/main/asciidoc/images/webauthn-register.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/src/main/asciidoc/security-webauthn.adoc b/docs/src/main/asciidoc/security-webauthn.adoc
index 09ee4ce6b24e2..ee8c82686c94c 100644
--- a/docs/src/main/asciidoc/security-webauthn.adoc
+++ b/docs/src/main/asciidoc/security-webauthn.adoc
@@ -274,13 +274,13 @@ public class WebAuthnCredential extends PanacheEntityBase {
public WebAuthnCredentialRecord toWebAuthnCredentialRecord() {
return WebAuthnCredentialRecord
.fromRequiredPersistedData(
- new RequiredPersistedData(user.userName, credentialId,
+ new RequiredPersistedData(user.username, credentialId,
aaguid, publicKey,
publicKeyAlgorithm, counter));
}
- public static List findByUserName(String userName) {
- return list("user.userName", userName);
+ public static List findByUsername(String username) {
+ return list("user.username", username);
}
public static WebAuthnCredential findByCredentialId(String credentialId) {
@@ -306,14 +306,14 @@ import jakarta.persistence.Table;
public class User extends PanacheEntity {
@Column(unique = true)
- public String userName;
+ public String username;
// non-owning side, so we can add more credentials later
@OneToOne(mappedBy = "user")
public WebAuthnCredential webAuthnCredential;
- public static User findByUserName(String userName) {
- return User.find("userName", userName).firstResult();
+ public static User findByUsername(String username) {
+ return User.find("username", username).firstResult();
}
}
----
@@ -350,9 +350,9 @@ public class MyWebAuthnSetup implements WebAuthnUserProvider {
@Transactional
@Override
- public Uni> findByUserName(String userId) {
+ public Uni> findByUsername(String userId) {
return Uni.createFrom().item(
- WebAuthnCredential.findByUserName(userId)
+ WebAuthnCredential.findByUsername(userId)
.stream()
.map(WebAuthnCredential::toWebAuthnCredentialRecord)
.toList());
@@ -372,9 +372,9 @@ public class MyWebAuthnSetup implements WebAuthnUserProvider {
@Override
public Uni store(WebAuthnCredentialRecord credentialRecord) {
User newUser = new User();
- // We can only store one credential per userName thanks to the unicity constraint
- // which will cause this transaction to fail and throw if the userName already exists
- newUser.userName = credentialRecord.getUserName();
+ // We can only store one credential per username thanks to the unicity constraint
+ // which will cause this transaction to fail and throw if the username already exists
+ newUser.username = credentialRecord.getUsername();
WebAuthnCredential credential = new WebAuthnCredential(credentialRecord, newUser);
credential.persist();
newUser.persist();
@@ -401,10 +401,10 @@ public class MyWebAuthnSetup implements WebAuthnUserProvider {
----
Warning: When implementing your own `WebAuthnUserProvider.store` method, make sure that you never allow creating
-new credentials for a `userName` that already exists. Otherwise you risk allowing third-parties to impersonate existing
+new credentials for a `username` that already exists. Otherwise you risk allowing third-parties to impersonate existing
users by letting them add their own credentials to existing accounts. If you want to allow existing users to register
more than one WebAuthn credential, you must make sure in `WebAuthnUserProvider.store` that the user is currently logged
-in under the same `userName` to which you want to add new credentials. In every other case, make sure to return a failed
+in under the same `username` to which you want to add new credentials. In every other case, make sure to return a failed
`Uni` from this method. In this particular example, this is checked using a unicity constraint on the user name, which
will cause the transaction to fail if the user already exists.
@@ -492,7 +492,7 @@ in `src/main/resources/META-INF/resources/index.html`:
Register
-
+
@@ -506,7 +506,7 @@ in `src/main/resources/META-INF/resources/index.html`:
fetch('/api/public/me')
.then(response => response.text())
- .then(name => result.append("User: "+name));
+ .then(username => result.append("User: "+username));
const loginButton = document.getElementById('login');
@@ -515,8 +515,8 @@ in `src/main/resources/META-INF/resources/index.html`:
webAuthn.login()
.then(x => fetch('/api/public/me'))
.then(response => response.text())
- .then(userName => {
- result.append("User: "+userName);
+ .then(username => {
+ result.append("User: "+username);
})
.catch(err => {
result.append("Login failed: "+err);
@@ -527,13 +527,13 @@ in `src/main/resources/META-INF/resources/index.html`:
const registerButton = document.getElementById('register');
registerButton.addEventListener("click", (e) => {
- var userName = document.getElementById('userNameRegister').value;
+ var username = document.getElementById('usernameRegister').value;
var firstName = document.getElementById('firstName').value;
var lastName = document.getElementById('lastName').value;
result.replaceChildren();
- webAuthn.register({ name: userName, displayName: firstName + " " + lastName })
+ webAuthn.register({ username: username, displayName: firstName + " " + lastName })
.then(body => {
- result.append("User: "+userName);
+ result.append("User: "+username);
})
.catch(err => {
result.append("Registration failed: "+err);
@@ -621,21 +621,14 @@ The Quarkus WebAuthn extension comes out of the box with these REST endpoints pr
=== Obtain a registration challenge
-`POST /q/webauthn/register-options-challenge`: Set up and obtain a registration challenge
+`GET /q/webauthn/register-options-challenge?username=&displayName=`: Set up and obtain a registration challenge
-This causes a cookie to be set for the challenge, it will be used by the registration step later.
+Query parameters:
-[source,json]
-.Request
-----
-{
- "name": "userName", <1>
- "displayName": "Mr Nice Guy" <2>
-}
-----
+- `username` is a username. Required.
+- `displayName` is a human-palatable name for the user account. Optional.
-<1> Required
-<2> Optional
+This causes a cookie to be set for the challenge, it will be used by the registration step later.
[source,json]
.Response
@@ -674,7 +667,11 @@ This causes a cookie to be set for the challenge, it will be used by the registr
=== Trigger a registration
-`POST /q/webauthn/register`: Trigger a registration
+`POST /q/webauthn/register?username=`: Trigger a registration
+
+Query parameters:
+
+- `username` is a username. Required.
This uses the challenge cookie set by the registration challenge and clears it. It
also uses your link:{webauthn-api}/io/quarkus/security/webauthn/WebAuthnUserProvider.html[`WebAuthnUserProvider`] to store the new credentials, and sets up
@@ -700,19 +697,13 @@ This returns a 204 with no body.
=== Obtain a login challenge
-`POST /q/webauthn/login-options-challenge`: Set up and obtain a login challenge
+`GET /q/webauthn/login-options-challenge?username=`: Set up and obtain a login challenge
-This causes a cookie to be set for the challenge, it will be used by the login step later.
+Query parameters:
-[source,json]
-.Request
-----
-{
- "name": "userName" <1>
-}
-----
+- `username` is a username. Optional in the case of https://www.w3.org/TR/webauthn-3/#discoverable-credential[Discoverable Credentials] (with PassKeys).
-<1> The name is optional, in the case of https://www.w3.org/TR/webauthn-3/#discoverable-credential[Discoverable Credentials] (with PassKeys)
+This causes a cookie to be set for the challenge, it will be used by the login step later.
[source,json]
.Response
@@ -855,7 +846,7 @@ for that registration, and returns a https://developer.mozilla.org/en-US/docs/We
[source,javascript]
----
-webAuthn.register({ name: userName, displayName: firstName + " " + lastName })
+webAuthn.register({ username: username, displayName: firstName + " " + lastName })
.then(body => {
// do something now that the user is registered
})
@@ -871,7 +862,7 @@ for that login, and returns a https://developer.mozilla.org/en-US/docs/Web/JavaS
[source,javascript]
----
-webAuthn.login({ name: userName }) <1>
+webAuthn.login({ username: username }) <1>
.then(body => {
// do something now that the user is logged in
})
@@ -880,7 +871,7 @@ webAuthn.login({ name: userName }) <1>
});
----
-<1> The name is optional, in the case of https://www.w3.org/TR/webauthn-3/#discoverable-credential[Discoverable Credentials] (with PassKeys)
+<1> The username is optional, in the case of https://www.w3.org/TR/webauthn-3/#discoverable-credential[Discoverable Credentials] (with PassKeys)
=== Only invoke the registration challenge and authenticator
@@ -891,7 +882,7 @@ in hidden form `input` elements, for example, and send it as part of a regular H
[source,javascript]
----
-webAuthn.registerClientSteps({ name: userName, displayName: firstName + " " + lastName })
+webAuthn.registerClientSteps({ username: username, displayName: firstName + " " + lastName })
.then(body => {
// store the registration JSON in form elements
document.getElementById('webAuthnId').value = body.id;
@@ -914,7 +905,7 @@ in hidden form `input` elements, for example, and send it as part of a regular H
[source,javascript]
----
-webAuthn.loginClientSteps({ name: userName }) <1>
+webAuthn.loginClientSteps({ username: username }) <1>
.then(body => {
// store the login JSON in form elements
document.getElementById('webAuthnId').value = body.id;
@@ -930,7 +921,7 @@ webAuthn.loginClientSteps({ name: userName }) <1>
});
----
-<1> The name is optional, in the case of https://www.w3.org/TR/webauthn-3/#discoverable-credential[Discoverable Credentials] (with PassKeys)
+<1> The username is optional, in the case of https://www.w3.org/TR/webauthn-3/#discoverable-credential[Discoverable Credentials] (with PassKeys)
== Handling login and registration endpoints yourself
@@ -986,9 +977,9 @@ public class MyWebAuthnSetup implements WebAuthnUserProvider {
@Transactional
@Override
- public Uni> findByUserName(String userName) {
+ public Uni> findByUsername(String username) {
return Uni.createFrom().item(
- WebAuthnCredential.findByUserName(userName)
+ WebAuthnCredential.findByUsername(username)
.stream()
.map(WebAuthnCredential::toWebAuthnCredentialRecord)
.toList());
@@ -1059,7 +1050,7 @@ public class LoginResource {
try {
WebAuthnCredentialRecord credentialRecord = this.webAuthnSecurity.login(webAuthnResponse, ctx).await().indefinitely();
- User user = User.findByUserName(credentialRecord.getUserName());
+ User user = User.findByUsername(credentialRecord.getUsername());
if(user == null) {
// Invalid user
return Response.status(Status.BAD_REQUEST).build();
@@ -1067,7 +1058,7 @@ public class LoginResource {
// bump the auth counter
user.webAuthnCredential.counter = credentialRecord.getCounter();
// make a login cookie
- this.webAuthnSecurity.rememberUser(credentialRecord.getUserName(), ctx);
+ this.webAuthnSecurity.rememberUser(credentialRecord.getUsername(), ctx);
return Response.ok().build();
} catch (Exception exception) {
// handle login failure - make a proper error response
@@ -1079,16 +1070,16 @@ public class LoginResource {
@Path("/register")
@POST
@Transactional
- public Response register(@RestForm String userName,
+ public Response register(@RestForm String username,
@BeanParam WebAuthnRegisterResponse webAuthnResponse,
RoutingContext ctx) {
// Input validation
- if(userName == null || userName.isEmpty()
+ if(username == null || username.isEmpty()
|| !webAuthnResponse.isSet() || !webAuthnResponse.isValid()) {
return Response.status(Status.BAD_REQUEST).build();
}
- User user = User.findByUserName(userName);
+ User user = User.findByUsername(username);
if(user != null) {
// Duplicate user
return Response.status(Status.BAD_REQUEST).build();
@@ -1096,15 +1087,15 @@ public class LoginResource {
try {
// store the user
WebAuthnCredentialRecord credentialRecord =
- webAuthnSecurity.register(userName, webAuthnResponse, ctx).await().indefinitely();
+ webAuthnSecurity.register(username, webAuthnResponse, ctx).await().indefinitely();
User newUser = new User();
- newUser.userName = credentialRecord.getUserName();
+ newUser.username = credentialRecord.getUsername();
WebAuthnCredential credential =
new WebAuthnCredential(credentialRecord, newUser);
credential.persist();
newUser.persist();
// make a login cookie
- this.webAuthnSecurity.rememberUser(newUser.userName, ctx);
+ this.webAuthnSecurity.rememberUser(newUser.username, ctx);
return Response.ok().build();
} catch (Exception ignored) {
// handle login failure
@@ -1214,26 +1205,26 @@ public class WebAuthnResourceTest {
testWebAuthn("admin", User.ADMIN, Endpoint.DEFAULT);
}
- private void testWebAuthn(String userName, User user, Endpoint endpoint) {
+ private void testWebAuthn(String username, User user, Endpoint endpoint) {
Filter cookieFilter = new RenardeCookieFilter();
WebAuthnHardware token = new WebAuthnHardware(url);
verifyLoggedOut(cookieFilter);
// two-step registration
- String challenge = WebAuthnEndpointHelper.obtainRegistrationChallenge(userName, cookieFilter);
+ String challenge = WebAuthnEndpointHelper.obtainRegistrationChallenge(username, cookieFilter);
JsonObject registrationJson = token.makeRegistrationJson(challenge);
if(endpoint == Endpoint.DEFAULT)
- WebAuthnEndpointHelper.invokeRegistration(userName, registrationJson, cookieFilter);
+ WebAuthnEndpointHelper.invokeRegistration(username, registrationJson, cookieFilter);
else {
invokeCustomEndpoint("/register", cookieFilter, request -> {
WebAuthnEndpointHelper.addWebAuthnRegistrationFormParameters(request, registrationJson);
- request.formParam("userName", userName);
+ request.formParam("username", username);
});
}
// verify that we can access logged-in endpoints
- verifyLoggedIn(cookieFilter, userName, user);
+ verifyLoggedIn(cookieFilter, username, user);
// logout
WebAuthnEndpointHelper.invokeLogout(cookieFilter);
@@ -1252,7 +1243,7 @@ public class WebAuthnResourceTest {
}
// verify that we can access logged-in endpoints
- verifyLoggedIn(cookieFilter, userName, user);
+ verifyLoggedIn(cookieFilter, username, user);
// logout
WebAuthnEndpointHelper.invokeLogout(cookieFilter);
@@ -1276,7 +1267,7 @@ public class WebAuthnResourceTest {
.cookie(WebAuthnEndpointHelper.getMainCookie(), Matchers.notNullValue());
}
- private void verifyLoggedIn(Filter cookieFilter, String userName, User user) {
+ private void verifyLoggedIn(Filter cookieFilter, String username, User user) {
// public API still good
RestAssured.given().filter(cookieFilter)
.when()
@@ -1290,7 +1281,7 @@ public class WebAuthnResourceTest {
.get("/api/public/me")
.then()
.statusCode(200)
- .body(Matchers.is(userName));
+ .body(Matchers.is(username));
// user API accessible
RestAssured.given().filter(cookieFilter)
@@ -1298,7 +1289,7 @@ public class WebAuthnResourceTest {
.get("/api/users/me")
.then()
.statusCode(200)
- .body(Matchers.is(userName));
+ .body(Matchers.is(username));
// admin API?
if(user == User.ADMIN) {
@@ -1381,7 +1372,7 @@ public class TestUserProvider extends MyWebAuthnSetup {
@Override
public Uni store(WebAuthnCredentialRecord credentialRecord) {
// this user is handled in the LoginResource endpoint manually
- if (credentialRecord.getUserName().equals("scooby")) {
+ if (credentialRecord.getUsername().equals("scooby")) {
return Uni.createFrom().voidItem();
}
return super.store(credentialRecord);
@@ -1392,7 +1383,7 @@ public class TestUserProvider extends MyWebAuthnSetup {
public Uni update(String credentialId, long counter) {
WebAuthnCredential credential = WebAuthnCredential.findByCredentialId(credentialId);
// this user is handled in the LoginResource endpoint manually
- if (credential.user.userName.equals("scooby")) {
+ if (credential.user.username.equals("scooby")) {
return Uni.createFrom().voidItem();
}
return super.update(credentialId, counter);
diff --git a/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/ManualResource.java b/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/ManualResource.java
index 42fd2c508e285..0eb35dfe100d9 100644
--- a/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/ManualResource.java
+++ b/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/ManualResource.java
@@ -29,7 +29,7 @@ public Uni register(@QueryParam("username") String username, @BeanParam
return security.register(username, register, ctx).map(authenticator -> {
// need to attach the authenticator to the user
userProvider.reallyStore(authenticator);
- security.rememberUser(authenticator.getUserName(), ctx);
+ security.rememberUser(authenticator.getUsername(), ctx);
return "OK";
});
}
@@ -40,7 +40,7 @@ public Uni login(@BeanParam WebAuthnLoginResponse login, RoutingContext
return security.login(login, ctx).map(authenticator -> {
// need to update the user's authenticator
userProvider.reallyUpdate(authenticator.getCredentialID(), authenticator.getCounter());
- security.rememberUser(authenticator.getUserName(), ctx);
+ security.rememberUser(authenticator.getUsername(), ctx);
return "OK";
});
}
diff --git a/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/TestResource.java b/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/TestResource.java
index f1415255f31c8..90160a8bb38fc 100644
--- a/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/TestResource.java
+++ b/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/TestResource.java
@@ -16,7 +16,7 @@ public class TestResource {
@Authenticated
@Path("secure")
@GET
- public String getUserName() {
+ public String getUsername() {
return identity.getPrincipal().getName() + ": " + identity.getRoles();
}
diff --git a/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnAndBasicAuthnTest.java b/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnAndBasicAuthnTest.java
index efa77f85bb7cf..1e9bc68a63ef3 100644
--- a/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnAndBasicAuthnTest.java
+++ b/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnAndBasicAuthnTest.java
@@ -55,7 +55,7 @@ public static void setupUsers() {
@Test
public void test() throws Exception {
- Assertions.assertTrue(userProvider.findByUserName("stev").await().indefinitely().isEmpty());
+ Assertions.assertTrue(userProvider.findByUsername("stev").await().indefinitely().isEmpty());
CookieFilter cookieFilter = new CookieFilter();
String challenge = WebAuthnEndpointHelper.obtainRegistrationChallenge("stev", cookieFilter);
WebAuthnHardware hardwareKey = new WebAuthnHardware(url);
@@ -79,9 +79,9 @@ public void test() throws Exception {
.cookie("quarkus-credential", Matchers.notNullValue());
// make sure we stored the user
- List users = userProvider.findByUserName("stev").await().indefinitely();
+ List users = userProvider.findByUsername("stev").await().indefinitely();
Assertions.assertEquals(1, users.size());
- Assertions.assertTrue(users.get(0).getUserName().equals("stev"));
+ Assertions.assertTrue(users.get(0).getUsername().equals("stev"));
Assertions.assertEquals(1, users.get(0).getCounter());
// make sure our login cookie works
diff --git a/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnAutomaticTest.java b/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnAutomaticTest.java
index ce1074c868e2b..b64600f2649ca 100644
--- a/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnAutomaticTest.java
+++ b/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnAutomaticTest.java
@@ -40,7 +40,7 @@ public void test() throws Exception {
.given().redirects().follow(false)
.get("/cheese").then().statusCode(302);
- Assertions.assertTrue(userProvider.findByUserName("stef").await().indefinitely().isEmpty());
+ Assertions.assertTrue(userProvider.findByUsername("stef").await().indefinitely().isEmpty());
CookieFilter cookieFilter = new CookieFilter();
WebAuthnHardware hardwareKey = new WebAuthnHardware(url);
String challenge = WebAuthnEndpointHelper.obtainRegistrationChallenge("stef", cookieFilter);
@@ -50,9 +50,9 @@ public void test() throws Exception {
WebAuthnEndpointHelper.invokeRegistration("stef", registration, cookieFilter);
// make sure we stored the user
- List users = userProvider.findByUserName("stef").await().indefinitely();
+ List users = userProvider.findByUsername("stef").await().indefinitely();
Assertions.assertEquals(1, users.size());
- Assertions.assertTrue(users.get(0).getUserName().equals("stef"));
+ Assertions.assertTrue(users.get(0).getUsername().equals("stef"));
Assertions.assertEquals(1, users.get(0).getCounter());
// make sure our login cookie works
@@ -68,9 +68,9 @@ public void test() throws Exception {
WebAuthnEndpointHelper.invokeLogin(login, cookieFilter);
// make sure we bumped the user
- users = userProvider.findByUserName("stef").await().indefinitely();
+ users = userProvider.findByUsername("stef").await().indefinitely();
Assertions.assertEquals(1, users.size());
- Assertions.assertTrue(users.get(0).getUserName().equals("stef"));
+ Assertions.assertTrue(users.get(0).getUsername().equals("stef"));
Assertions.assertEquals(2, users.get(0).getCounter());
// make sure our login cookie still works
@@ -86,9 +86,9 @@ public void test() throws Exception {
WebAuthnEndpointHelper.invokeLogin(login, cookieFilter);
// make sure we bumped the user
- users = userProvider.findByUserName("stef").await().indefinitely();
+ users = userProvider.findByUsername("stef").await().indefinitely();
Assertions.assertEquals(1, users.size());
- Assertions.assertTrue(users.get(0).getUserName().equals("stef"));
+ Assertions.assertTrue(users.get(0).getUsername().equals("stef"));
Assertions.assertEquals(3, users.get(0).getCounter());
// make sure our login cookie still works
diff --git a/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnBlockingTestUserProvider.java b/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnBlockingTestUserProvider.java
index 9fd20f321a561..49786959dff82 100644
--- a/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnBlockingTestUserProvider.java
+++ b/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnBlockingTestUserProvider.java
@@ -24,9 +24,9 @@ public Uni findByCredentialId(String credId) {
}
@Override
- public Uni> findByUserName(String userId) {
+ public Uni> findByUsername(String userId) {
assertBlockingAllowed();
- return super.findByUserName(userId);
+ return super.findByUsername(userId);
}
@Override
diff --git a/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnManualCustomCookiesTest.java b/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnManualCustomCookiesTest.java
index c9c15baf3c6c8..d2b0ef0f4643d 100644
--- a/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnManualCustomCookiesTest.java
+++ b/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnManualCustomCookiesTest.java
@@ -57,7 +57,7 @@ public void test() throws Exception {
.given().redirects().follow(false)
.get("/cheese").then().statusCode(302);
- Assertions.assertTrue(userProvider.findByUserName("stef").await().indefinitely().isEmpty());
+ Assertions.assertTrue(userProvider.findByUsername("stef").await().indefinitely().isEmpty());
CookieFilter cookieFilter = new CookieFilter();
String challenge = WebAuthnEndpointHelper.obtainRegistrationChallenge("stef", cookieFilter);
WebAuthnHardware hardwareKey = new WebAuthnHardware(url);
@@ -77,9 +77,9 @@ public void test() throws Exception {
.cookie("main-cookie", Matchers.notNullValue());
// make sure we stored the user
- List users = userProvider.findByUserName("stef").await().indefinitely();
+ List users = userProvider.findByUsername("stef").await().indefinitely();
Assertions.assertEquals(1, users.size());
- Assertions.assertTrue(users.get(0).getUserName().equals("stef"));
+ Assertions.assertTrue(users.get(0).getUsername().equals("stef"));
Assertions.assertEquals(1, users.get(0).getCounter());
// make sure our login cookie works
@@ -104,9 +104,9 @@ public void test() throws Exception {
.cookie("main-cookie", Matchers.notNullValue());
// make sure we bumped the user
- users = userProvider.findByUserName("stef").await().indefinitely();
+ users = userProvider.findByUsername("stef").await().indefinitely();
Assertions.assertEquals(1, users.size());
- Assertions.assertTrue(users.get(0).getUserName().equals("stef"));
+ Assertions.assertTrue(users.get(0).getUsername().equals("stef"));
Assertions.assertEquals(2, users.get(0).getCounter());
// make sure our login cookie still works
diff --git a/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnManualTest.java b/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnManualTest.java
index ef2a4c69886ca..e54ae25e2a92f 100644
--- a/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnManualTest.java
+++ b/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnManualTest.java
@@ -56,7 +56,7 @@ public void test() throws Exception {
.given().redirects().follow(false)
.get("/cheese").then().statusCode(302);
- Assertions.assertTrue(userProvider.findByUserName("stef").await().indefinitely().isEmpty());
+ Assertions.assertTrue(userProvider.findByUsername("stef").await().indefinitely().isEmpty());
CookieFilter cookieFilter = new CookieFilter();
String challenge = WebAuthnEndpointHelper.obtainRegistrationChallenge("stef", cookieFilter);
WebAuthnHardware hardwareKey = new WebAuthnHardware(url);
@@ -78,9 +78,9 @@ public void test() throws Exception {
.cookie("quarkus-credential", Matchers.notNullValue());
// make sure we stored the user
- List users = userProvider.findByUserName("stef").await().indefinitely();
+ List users = userProvider.findByUsername("stef").await().indefinitely();
Assertions.assertEquals(1, users.size());
- Assertions.assertTrue(users.get(0).getUserName().equals("stef"));
+ Assertions.assertTrue(users.get(0).getUsername().equals("stef"));
Assertions.assertEquals(1, users.get(0).getCounter());
// make sure our login cookie works
@@ -107,9 +107,9 @@ public void test() throws Exception {
.cookie("quarkus-credential", Matchers.notNullValue());
// make sure we bumped the user
- users = userProvider.findByUserName("stef").await().indefinitely();
+ users = userProvider.findByUsername("stef").await().indefinitely();
Assertions.assertEquals(1, users.size());
- Assertions.assertTrue(users.get(0).getUserName().equals("stef"));
+ Assertions.assertTrue(users.get(0).getUsername().equals("stef"));
Assertions.assertEquals(2, users.get(0).getCounter());
// make sure our login cookie still works
@@ -127,15 +127,15 @@ public void test() throws Exception {
() -> WebAuthnEndpointHelper.invokeLogin(defaultLogin, finalCookieFilter));
// make sure we did not bump the user
- users = userProvider.findByUserName("stef").await().indefinitely();
+ users = userProvider.findByUsername("stef").await().indefinitely();
Assertions.assertEquals(1, users.size());
- Assertions.assertTrue(users.get(0).getUserName().equals("stef"));
+ Assertions.assertTrue(users.get(0).getUsername().equals("stef"));
Assertions.assertEquals(2, users.get(0).getCounter());
}
@Test
public void checkDefaultRegistrationDisabled() {
- Assertions.assertTrue(userProvider.findByUserName("stef").await().indefinitely().isEmpty());
+ Assertions.assertTrue(userProvider.findByUsername("stef").await().indefinitely().isEmpty());
CookieFilter cookieFilter = new CookieFilter();
WebAuthnHardware hardwareKey = new WebAuthnHardware(url);
String challenge = WebAuthnEndpointHelper.obtainRegistrationChallenge("stef", cookieFilter);
@@ -146,7 +146,7 @@ public void checkDefaultRegistrationDisabled() {
() -> WebAuthnEndpointHelper.invokeRegistration("stef", registration, cookieFilter));
// make sure we did not create any user
- Assertions.assertTrue(userProvider.findByUserName("stef").await().indefinitely().isEmpty());
+ Assertions.assertTrue(userProvider.findByUsername("stef").await().indefinitely().isEmpty());
}
private void checkLoggedIn(CookieFilter cookieFilter) {
diff --git a/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnManualTestUserProvider.java b/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnManualTestUserProvider.java
index be5779656c498..86d561d3321d1 100644
--- a/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnManualTestUserProvider.java
+++ b/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnManualTestUserProvider.java
@@ -25,9 +25,9 @@ public Uni findByCredentialId(String credId) {
}
@Override
- public Uni> findByUserName(String userId) {
+ public Uni> findByUsername(String userId) {
assertRequestContext();
- return super.findByUserName(userId);
+ return super.findByUsername(userId);
}
private void assertRequestContext() {
diff --git a/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnNonBlockingTestUserProvider.java b/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnNonBlockingTestUserProvider.java
index 4cab358e2a838..7d88c1c620187 100644
--- a/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnNonBlockingTestUserProvider.java
+++ b/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnNonBlockingTestUserProvider.java
@@ -22,9 +22,9 @@ public Uni findByCredentialId(String credId) {
}
@Override
- public Uni> findByUserName(String userId) {
+ public Uni> findByUsername(String userId) {
assertBlockingNotAllowed();
- return super.findByUserName(userId);
+ return super.findByUsername(userId);
}
@Override
diff --git a/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnOriginsTest.java b/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnOriginsTest.java
index 4acb80be4f140..faba447abe20a 100644
--- a/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnOriginsTest.java
+++ b/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnOriginsTest.java
@@ -9,7 +9,6 @@
import io.quarkus.test.security.webauthn.WebAuthnTestUserProvider;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
-import io.vertx.core.json.JsonObject;
public class WebAuthnOriginsTest {
@@ -24,10 +23,9 @@ public class WebAuthnOriginsTest {
public void testLoginRpFromFirstOrigin() {
RestAssured
.given()
- .body(new JsonObject()
- .put("name", "foo").encode())
- .contentType(ContentType.JSON)
- .post("/q/webauthn/register-options-challenge")
+ .contentType(ContentType.URLENC)
+ .queryParam("username", "foo")
+ .get("/q/webauthn/register-options-challenge")
.then()
.log().all()
.statusCode(200)
diff --git a/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnTest.java b/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnTest.java
index f671a33f0cd1a..03cf9cec1850a 100644
--- a/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnTest.java
+++ b/extensions/security-webauthn/deployment/src/test/java/io/quarkus/security/webauthn/test/WebAuthnTest.java
@@ -10,7 +10,6 @@
import io.restassured.RestAssured;
import io.restassured.filter.cookie.CookieFilter;
import io.restassured.http.ContentType;
-import io.vertx.core.json.JsonObject;
public class WebAuthnTest {
@@ -31,10 +30,9 @@ public void testJavaScriptFile() {
public void testLoginRpFromFirstOrigin() {
RestAssured
.given()
- .body(new JsonObject()
- .put("name", "foo").encode())
.contentType(ContentType.JSON)
- .post("/q/webauthn/register-options-challenge")
+ .queryParam("username", "foo")
+ .get("/q/webauthn/register-options-challenge")
.then()
.statusCode(200)
.contentType(ContentType.JSON)
@@ -48,19 +46,17 @@ public void testRegisterChallengeIsEqualAcrossCalls() {
String challenge = RestAssured
.given()
.filter(cookieFilter)
- .body(new JsonObject()
- .put("name", "foo").encode())
- .contentType(ContentType.JSON)
- .post("/q/webauthn/register-options-challenge")
+ .contentType(ContentType.URLENC)
+ .queryParam("username", "foo")
+ .get("/q/webauthn/register-options-challenge")
.jsonPath().get("challenge");
RestAssured
.given()
.filter(cookieFilter)
- .body(new JsonObject()
- .put("name", "foo").encode())
- .contentType(ContentType.JSON)
- .post("/q/webauthn/register-options-challenge")
+ .contentType(ContentType.URLENC)
+ .queryParam("username", "foo")
+ .get("/q/webauthn/register-options-challenge")
.then()
.statusCode(200)
.contentType(ContentType.JSON)
@@ -74,17 +70,15 @@ public void testLoginChallengeIsEqualAcrossCalls() {
String challenge = RestAssured
.given()
.filter(cookieFilter)
- .body(new JsonObject().encode())
- .contentType(ContentType.JSON)
- .post("/q/webauthn/login-options-challenge")
+ .contentType(ContentType.URLENC)
+ .get("/q/webauthn/login-options-challenge")
.jsonPath().get("challenge");
RestAssured
.given()
.filter(cookieFilter)
- .body(new JsonObject().encode())
- .contentType(ContentType.JSON)
- .post("/q/webauthn/login-options-challenge")
+ .contentType(ContentType.URLENC)
+ .get("/q/webauthn/login-options-challenge")
.then()
.statusCode(200)
.contentType(ContentType.JSON)
diff --git a/extensions/security-webauthn/runtime/src/main/java/io/quarkus/security/webauthn/WebAuthnAuthenticatorStorage.java b/extensions/security-webauthn/runtime/src/main/java/io/quarkus/security/webauthn/WebAuthnAuthenticatorStorage.java
index bc67b739be83b..a1031100ddfc1 100644
--- a/extensions/security-webauthn/runtime/src/main/java/io/quarkus/security/webauthn/WebAuthnAuthenticatorStorage.java
+++ b/extensions/security-webauthn/runtime/src/main/java/io/quarkus/security/webauthn/WebAuthnAuthenticatorStorage.java
@@ -26,8 +26,8 @@ public class WebAuthnAuthenticatorStorage {
@Inject
Vertx vertx;
- public Uni> findByUserName(String userName) {
- return runPotentiallyBlocking(() -> userProvider.findByUserName(userName));
+ public Uni> findByUsername(String username) {
+ return runPotentiallyBlocking(() -> userProvider.findByUsername(username));
}
public Uni findByCredID(String credID) {
diff --git a/extensions/security-webauthn/runtime/src/main/java/io/quarkus/security/webauthn/WebAuthnController.java b/extensions/security-webauthn/runtime/src/main/java/io/quarkus/security/webauthn/WebAuthnController.java
index bbe16c5d3282c..083a8b7cb5b26 100644
--- a/extensions/security-webauthn/runtime/src/main/java/io/quarkus/security/webauthn/WebAuthnController.java
+++ b/extensions/security-webauthn/runtime/src/main/java/io/quarkus/security/webauthn/WebAuthnController.java
@@ -47,12 +47,9 @@ public void wellKnown(RoutingContext ctx) {
*/
public void registerOptionsChallenge(RoutingContext ctx) {
try {
- // might throw runtime exception if there's no json or is bad formed
- final JsonObject webauthnRegister = ctx.getBodyAsJson();
-
- String name = webauthnRegister.getString("name");
- String displayName = webauthnRegister.getString("displayName");
- withContext(() -> security.getRegisterChallenge(name, displayName, ctx))
+ String username = ctx.queryParams().get("username");
+ String displayName = ctx.queryParams().get("displayName");
+ withContext(() -> security.getRegisterChallenge(username, displayName, ctx))
.map(challenge -> security.toJsonString(challenge))
.subscribe().with(challenge -> ok(ctx, challenge), ctx::fail);
@@ -77,11 +74,8 @@ private Uni withContext(Supplier> uni) {
*/
public void loginOptionsChallenge(RoutingContext ctx) {
try {
- // might throw runtime exception if there's no json or is bad formed
- final JsonObject webauthnLogin = ctx.getBodyAsJson();
-
- String name = webauthnLogin.getString("name");
- withContext(() -> security.getLoginChallenge(name, ctx))
+ String username = ctx.queryParams().get("username");
+ withContext(() -> security.getLoginChallenge(username, ctx))
.map(challenge -> security.toJsonString(challenge))
.subscribe().with(challenge -> ok(ctx, challenge), ctx::fail);
@@ -106,7 +100,7 @@ public void login(RoutingContext ctx) {
withContext(() -> security.login(webauthnResp, ctx))
.onItem().call(record -> security.storage().update(record.getCredentialID(), record.getCounter()))
.subscribe().with(record -> {
- security.rememberUser(record.getUserName(), ctx);
+ security.rememberUser(record.getUsername(), ctx);
ok(ctx);
}, x -> ctx.fail(400, x));
} catch (IllegalArgumentException e) {
@@ -131,7 +125,7 @@ public void register(RoutingContext ctx) {
withContext(() -> security.register(username, webauthnResp, ctx))
.onItem().call(record -> security.storage().create(record))
.subscribe().with(record -> {
- security.rememberUser(record.getUserName(), ctx);
+ security.rememberUser(record.getUsername(), ctx);
ok(ctx);
}, x -> ctx.fail(400, x));
} catch (IllegalArgumentException e) {
diff --git a/extensions/security-webauthn/runtime/src/main/java/io/quarkus/security/webauthn/WebAuthnCredentialRecord.java b/extensions/security-webauthn/runtime/src/main/java/io/quarkus/security/webauthn/WebAuthnCredentialRecord.java
index 9deedc2ffa5cf..1739ac63adfbb 100644
--- a/extensions/security-webauthn/runtime/src/main/java/io/quarkus/security/webauthn/WebAuthnCredentialRecord.java
+++ b/extensions/security-webauthn/runtime/src/main/java/io/quarkus/security/webauthn/WebAuthnCredentialRecord.java
@@ -35,28 +35,28 @@
*/
public class WebAuthnCredentialRecord extends CredentialRecordImpl {
- private String userName;
+ private String username;
/*
* This is used for registering
*/
- public WebAuthnCredentialRecord(String userName,
+ public WebAuthnCredentialRecord(String username,
AttestationObject attestationObject,
CollectedClientData clientData,
AuthenticationExtensionsClientOutputs clientExtensions,
Set transports) {
super(attestationObject, clientData, clientExtensions, transports);
- this.userName = userName;
+ this.username = username;
}
/*
* This is used for login
*/
- private WebAuthnCredentialRecord(String userName,
+ private WebAuthnCredentialRecord(String username,
long counter,
AttestedCredentialData attestedCredentialData) {
super(null, null, null, null, counter, attestedCredentialData, null, null, null, null);
- this.userName = userName;
+ this.username = username;
}
/**
@@ -76,8 +76,8 @@ public long getCounter() {
*
* @return the username for this credential record
*/
- public String getUserName() {
- return userName;
+ public String getUsername() {
+ return username;
}
/**
@@ -97,7 +97,7 @@ public String getCredentialID() {
* @return the fields required to be persisted.
*/
public RequiredPersistedData getRequiredPersistedData() {
- return new RequiredPersistedData(getUserName(),
+ return new RequiredPersistedData(getUsername(),
getCredentialID(),
getAttestedCredentialData().getAaguid().getValue(),
getAttestedCredentialData().getCOSEKey().getPublicKey().getEncoded(),
@@ -143,7 +143,7 @@ public static WebAuthnCredentialRecord fromRequiredPersistedData(RequiredPersist
AAGUID aaguid = new AAGUID(persistedData.aaguid());
AttestedCredentialData attestedCredentialData = new AttestedCredentialData(aaguid, credentialId, coseKey);
- return new WebAuthnCredentialRecord(persistedData.userName(), counter, attestedCredentialData);
+ return new WebAuthnCredentialRecord(persistedData.username(), counter, attestedCredentialData);
}
/**
@@ -153,7 +153,7 @@ public record RequiredPersistedData(
/**
* The user name. A single user name may be associated with multiple WebAuthn credentials.
*/
- String userName,
+ String username,
/**
* The credential ID. This must be unique. See https://w3c.github.io/webauthn/#credential-id
*/
diff --git a/extensions/security-webauthn/runtime/src/main/java/io/quarkus/security/webauthn/WebAuthnRecorder.java b/extensions/security-webauthn/runtime/src/main/java/io/quarkus/security/webauthn/WebAuthnRecorder.java
index f23f509f74dd0..5fb56a234798e 100644
--- a/extensions/security-webauthn/runtime/src/main/java/io/quarkus/security/webauthn/WebAuthnRecorder.java
+++ b/extensions/security-webauthn/runtime/src/main/java/io/quarkus/security/webauthn/WebAuthnRecorder.java
@@ -38,9 +38,9 @@ public void setupRoutes(BeanContainer beanContainer, RuntimeValue router
BodyHandler bodyHandler = BodyHandler.create();
// FIXME: paths configurable
// prefix is the non-application root path, ends with a slash: defaults to /q/
- router.post(prefix + "webauthn/login-options-challenge").handler(bodyHandler)
+ router.get(prefix + "webauthn/login-options-challenge").handler(bodyHandler)
.handler(controller::loginOptionsChallenge);
- router.post(prefix + "webauthn/register-options-challenge").handler(bodyHandler)
+ router.get(prefix + "webauthn/register-options-challenge").handler(bodyHandler)
.handler(controller::registerOptionsChallenge);
if (config.getValue().enableLoginEndpoint().orElse(false)) {
router.post(prefix + "webauthn/login").handler(bodyHandler).handler(controller::login);
diff --git a/extensions/security-webauthn/runtime/src/main/java/io/quarkus/security/webauthn/WebAuthnSecurity.java b/extensions/security-webauthn/runtime/src/main/java/io/quarkus/security/webauthn/WebAuthnSecurity.java
index a489f5b892f92..7e2df1ea59900 100644
--- a/extensions/security-webauthn/runtime/src/main/java/io/quarkus/security/webauthn/WebAuthnSecurity.java
+++ b/extensions/security-webauthn/runtime/src/main/java/io/quarkus/security/webauthn/WebAuthnSecurity.java
@@ -312,30 +312,30 @@ private static byte[] uUIDBytes(UUID uuid) {
}
/**
- * Obtains a registration challenge for the given required userName and displayName. This will also
+ * Obtains a registration challenge for the given required username and displayName. This will also
* create and save a challenge in a session cookie.
*
- * @param userName the userName for the registration
+ * @param username the username for the registration
* @param displayName the displayName for the registration
* @param ctx the Vert.x context
* @return the registration challenge.
*/
@SuppressWarnings("unused")
- public Uni getRegisterChallenge(String userName, String displayName,
+ public Uni getRegisterChallenge(String username, String displayName,
RoutingContext ctx) {
- if (userName == null || userName.isEmpty()) {
+ if (username == null || username.isEmpty()) {
return Uni.createFrom().failure(new IllegalArgumentException("Username is required"));
}
- // default displayName to userName, but it's required really
+ // default displayName to username, but it's required really
if (displayName == null || displayName.isEmpty()) {
- displayName = userName;
+ displayName = username;
}
String finalDisplayName = displayName;
String challenge = getOrCreateChallenge(ctx);
Origin origin = Origin.create(!this.origins.isEmpty() ? this.origins.get(0) : ctx.request().absoluteURI());
String rpId = this.rpId != null ? this.rpId : origin.getHost();
- return storage.findByUserName(userName)
+ return storage.findByUsername(username)
.map(credentials -> {
List excluded;
// See https://github.com/quarkusio/quarkus/issues/44292 for why this is currently disabled
@@ -355,7 +355,7 @@ public Uni getRegisterChallenge(String userN
rpName),
new PublicKeyCredentialUserEntity(
uUIDBytes(UUID.randomUUID()),
- userName,
+ username,
finalDisplayName),
new DefaultChallenge(challenge),
pubKeyCredParams,
@@ -379,30 +379,30 @@ public Uni getRegisterChallenge(String userN
}
/**
- * Obtains a login challenge for the given optional userName. This will also
+ * Obtains a login challenge for the given optional username. This will also
* create and save a challenge in a session cookie.
*
- * @param userName the optional userName for the login
+ * @param username the optional username for the login
* @param ctx the Vert.x context
* @return the login challenge.
*/
@SuppressWarnings("unused")
- public Uni getLoginChallenge(String userName, RoutingContext ctx) {
+ public Uni getLoginChallenge(String username, RoutingContext ctx) {
// Username is not required with passkeys
- if (userName == null) {
- userName = "";
+ if (username == null) {
+ username = "";
}
- String finalUserName = userName;
+ String finalUsername = username;
String challenge = getOrCreateChallenge(ctx);
Origin origin = Origin.create(!this.origins.isEmpty() ? this.origins.get(0) : ctx.request().absoluteURI());
String rpId = this.rpId != null ? this.rpId : origin.getHost();
// do not attempt to look users up if there's no user name
Uni> credentialsUni;
- if (userName.isEmpty()) {
+ if (username.isEmpty()) {
credentialsUni = Uni.createFrom().item(Collections.emptyList());
} else {
- credentialsUni = storage.findByUserName(userName);
+ credentialsUni = storage.findByUsername(username);
}
return credentialsUni
.map(credentials -> {
@@ -411,7 +411,7 @@ public Uni getLoginChallenge(String userName,
if (false) {
if (credentials.isEmpty()) {
- throw new RuntimeException("No credentials found for " + finalUserName);
+ throw new RuntimeException("No credentials found for " + finalUsername);
}
allowedCredentials = new ArrayList<>(credentials.size());
for (WebAuthnCredentialRecord credential : credentials) {
diff --git a/extensions/security-webauthn/runtime/src/main/java/io/quarkus/security/webauthn/WebAuthnUserProvider.java b/extensions/security-webauthn/runtime/src/main/java/io/quarkus/security/webauthn/WebAuthnUserProvider.java
index 03b58ce4924b3..d90f43e694767 100644
--- a/extensions/security-webauthn/runtime/src/main/java/io/quarkus/security/webauthn/WebAuthnUserProvider.java
+++ b/extensions/security-webauthn/runtime/src/main/java/io/quarkus/security/webauthn/WebAuthnUserProvider.java
@@ -15,11 +15,11 @@ public interface WebAuthnUserProvider {
/**
* Look up a WebAuthn credential by username. This should return an empty list Uni if the user name is not found.
*
- * @param userName the username
+ * @param username the username
* @return a list of credentials for this username, or an empty list if there are no credentials or if the user name is
* not found.
*/
- public Uni> findByUserName(String userName);
+ public Uni> findByUsername(String username);
/**
* Look up a WebAuthn credential by credential ID, this should return an exception Uni rather than return a null-item Uni
@@ -53,19 +53,18 @@ public default Uni update(String credentialId, long counter) {
* {@link WebAuthnSecurity#register(WebAuthnRegisterResponse, io.vertx.ext.web.RoutingContext)}
*
* Make sure that you never allow creating
- * new credentials for a `userName` that already exists. Otherwise you risk allowing third-parties to impersonate existing
+ * new credentials for a `username` that already exists. Otherwise you risk allowing third-parties to impersonate existing
* users by letting them add their own credentials to existing accounts. If you want to allow existing users to register
* more than one WebAuthn credential, you must make sure that the user is currently logged
- * in under the same userName to which you want to add new credentials. In every other case, make sure to
+ * in under the same username to which you want to add new credentials. In every other case, make sure to
* return a failed
* {@link Uni} from this method.
*
* The default behaviour is to not do anything.
*
- * @param userName the userName's credentials
* @param credentialRecord the new credentials to store
* @return a uni completion object
- * @throws Exception a failed {@link Uni} if the credentialId already exists, or the userName
+ * @throws Exception a failed {@link Uni} if the credentialId already exists, or the username
* already
* has a credential and you disallow having more, or if trying to add credentials to other users than the current
* user.
@@ -77,10 +76,10 @@ public default Uni store(WebAuthnCredentialRecord credentialRecord) {
/**
* Returns the set of roles for the given username
*
- * @param userName the username
+ * @param username the username
* @return the set of roles (defaults to an empty set)
*/
- public default Set getRoles(String userName) {
+ public default Set getRoles(String username) {
return Collections.emptySet();
}
}
diff --git a/extensions/security-webauthn/runtime/src/main/resources/webauthn.js b/extensions/security-webauthn/runtime/src/main/resources/webauthn.js
index cc91864350831..c9a88f47be721 100644
--- a/extensions/security-webauthn/runtime/src/main/resources/webauthn.js
+++ b/extensions/security-webauthn/runtime/src/main/resources/webauthn.js
@@ -120,13 +120,12 @@
if (!self.registerOptionsChallengePath) {
return Promise.reject('Register challenge path missing form the initial configuration!');
}
- return self.fetchWithCsrf(self.registerOptionsChallengePath, {
- method: 'POST',
+ return self.fetchWithCsrf(self.registerOptionsChallengePath + "?" + new URLSearchParams({username: user.username, displayName: user.displayName}).toString(), {
+ method: 'GET',
headers: {
'Accept': 'application/json',
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify(user || {})
+ 'Content-Type': 'application/x-www-form-urlencoded'
+ }
})
.then(res => {
if (res.status === 200) {
@@ -164,12 +163,12 @@
if (!self.registerPath) {
throw new Error('Register path is missing!');
}
- if (!user || !user.name) {
- return Promise.reject('User name (user.name) required');
+ if (!user || !user.username) {
+ return Promise.reject('User name (user.username) required');
}
return self.registerClientSteps(user)
.then(body => {
- return self.fetchWithCsrf(self.registerPath + "?" + new URLSearchParams({username: user.name}).toString(), {
+ return self.fetchWithCsrf(self.registerPath + "?" + new URLSearchParams({username: user.username}).toString(), {
method: 'POST',
headers: {
'Accept': 'application/json',
@@ -215,13 +214,16 @@
if (!self.loginOptionsChallengePath) {
return Promise.reject('Login challenge path missing from the initial configuration!');
}
- return self.fetchWithCsrf(self.loginOptionsChallengePath, {
- method: 'POST',
+ let path = self.loginOptionsChallengePath
+ if (user != null && user.username != null) {
+ path = path + "?" + new URLSearchParams({username: user.username}).toString()
+ }
+ return self.fetchWithCsrf(path, {
+ method: 'GET',
headers: {
'Accept': 'application/json',
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify(user || {})
+ 'Content-Type': 'application/x-www-form-urlencoded'
+ }
})
.then(res => {
if (res.status === 200) {
diff --git a/integration-tests/security-webauthn/src/main/java/io/quarkus/it/security/webauthn/LoginResource.java b/integration-tests/security-webauthn/src/main/java/io/quarkus/it/security/webauthn/LoginResource.java
index a34e51eb8e9b0..57314c65f97cc 100644
--- a/integration-tests/security-webauthn/src/main/java/io/quarkus/it/security/webauthn/LoginResource.java
+++ b/integration-tests/security-webauthn/src/main/java/io/quarkus/it/security/webauthn/LoginResource.java
@@ -26,17 +26,17 @@ public class LoginResource {
@Path("/login")
@POST
@WithTransaction
- public Uni login(@RestForm String userName,
+ public Uni login(@RestForm String username,
@BeanParam WebAuthnLoginResponse webAuthnResponse,
RoutingContext ctx) {
// Input validation
- if (userName == null || userName.isEmpty()
+ if (username == null || username.isEmpty()
|| !webAuthnResponse.isSet()
|| !webAuthnResponse.isValid()) {
return Uni.createFrom().item(Response.status(Status.BAD_REQUEST).build());
}
- Uni userUni = User.findByUserName(userName);
+ Uni userUni = User.findByUsername(username);
return userUni.flatMap(user -> {
if (user == null) {
// Invalid user
@@ -49,7 +49,7 @@ public Uni login(@RestForm String userName,
.invoke(auth -> user.webAuthnCredential.counter = auth.getCounter())
.map(auth -> {
// make a login cookie
- this.webAuthnSecurity.rememberUser(auth.getUserName(), ctx);
+ this.webAuthnSecurity.rememberUser(auth.getUsername(), ctx);
return Response.ok().build();
})
// handle login failure
@@ -65,29 +65,29 @@ public Uni login(@RestForm String userName,
@Path("/register")
@POST
@WithTransaction
- public Uni register(@RestForm String userName,
+ public Uni register(@RestForm String username,
@BeanParam WebAuthnRegisterResponse webAuthnResponse,
RoutingContext ctx) {
// Input validation
- if (userName == null || userName.isEmpty()
+ if (username == null || username.isEmpty()
|| !webAuthnResponse.isSet()
|| !webAuthnResponse.isValid()) {
return Uni.createFrom().item(Response.status(Status.BAD_REQUEST).build());
}
- Uni userUni = User.findByUserName(userName);
+ Uni userUni = User.findByUsername(username);
return userUni.flatMap(user -> {
if (user != null) {
// Duplicate user
return Uni.createFrom().item(Response.status(Status.BAD_REQUEST).build());
}
- Uni authenticator = this.webAuthnSecurity.register(userName, webAuthnResponse, ctx);
+ Uni authenticator = this.webAuthnSecurity.register(username, webAuthnResponse, ctx);
return authenticator
// store the user
.flatMap(auth -> {
User newUser = new User();
- newUser.userName = auth.getUserName();
+ newUser.username = auth.getUsername();
WebAuthnCredential credential = new WebAuthnCredential(auth, newUser);
return credential.persist()
.flatMap(c -> newUser. persist());
@@ -95,7 +95,7 @@ public Uni register(@RestForm String userName,
})
.map(newUser -> {
// make a login cookie
- this.webAuthnSecurity.rememberUser(newUser.userName, ctx);
+ this.webAuthnSecurity.rememberUser(newUser.username, ctx);
return Response.ok().build();
})
// handle login failure
diff --git a/integration-tests/security-webauthn/src/main/java/io/quarkus/it/security/webauthn/MyWebAuthnSetup.java b/integration-tests/security-webauthn/src/main/java/io/quarkus/it/security/webauthn/MyWebAuthnSetup.java
index 15423104b0f17..a3e52a38e0a6d 100644
--- a/integration-tests/security-webauthn/src/main/java/io/quarkus/it/security/webauthn/MyWebAuthnSetup.java
+++ b/integration-tests/security-webauthn/src/main/java/io/quarkus/it/security/webauthn/MyWebAuthnSetup.java
@@ -17,8 +17,8 @@ public class MyWebAuthnSetup implements WebAuthnUserProvider {
@WithTransaction
@Override
- public Uni> findByUserName(String userName) {
- return WebAuthnCredential.findByUserName(userName)
+ public Uni> findByUsername(String username) {
+ return WebAuthnCredential.findByUsername(username)
.map(list -> list.stream().map(WebAuthnCredential::toWebAuthnCredentialRecord).toList());
}
@@ -34,11 +34,11 @@ public Uni findByCredentialId(String credentialId) {
@Override
public Uni store(WebAuthnCredentialRecord credentialRecord) {
// this user is handled in the LoginResource endpoint manually
- if (credentialRecord.getUserName().equals("scooby")) {
+ if (credentialRecord.getUsername().equals("scooby")) {
return Uni.createFrom().voidItem();
}
User newUser = new User();
- newUser.userName = credentialRecord.getUserName();
+ newUser.username = credentialRecord.getUsername();
WebAuthnCredential credential = new WebAuthnCredential(credentialRecord, newUser);
return credential.persist()
.flatMap(c -> newUser.persist())
@@ -51,7 +51,7 @@ public Uni update(String credentialId, long counter) {
return WebAuthnCredential.findByCredentialId(credentialId)
.invoke(credential -> {
// this user is handled in the LoginResource endpoint manually
- if (!credential.user.userName.equals("scooby")) {
+ if (!credential.user.username.equals("scooby")) {
credential.counter = counter;
}
})
@@ -59,8 +59,8 @@ public Uni update(String credentialId, long counter) {
}
@Override
- public Set getRoles(String userId) {
- if (userId.equals("admin")) {
+ public Set getRoles(String username) {
+ if (username.equals("admin")) {
Set ret = new HashSet<>();
ret.add("user");
ret.add("admin");
diff --git a/integration-tests/security-webauthn/src/main/java/io/quarkus/it/security/webauthn/User.java b/integration-tests/security-webauthn/src/main/java/io/quarkus/it/security/webauthn/User.java
index dc4861726bca8..411027ea31820 100644
--- a/integration-tests/security-webauthn/src/main/java/io/quarkus/it/security/webauthn/User.java
+++ b/integration-tests/security-webauthn/src/main/java/io/quarkus/it/security/webauthn/User.java
@@ -13,13 +13,13 @@
public class User extends PanacheEntity {
@Column(unique = true)
- public String userName;
+ public String username;
// non-owning side, so we can add more credentials later
@OneToOne(mappedBy = "user")
public WebAuthnCredential webAuthnCredential;
- public static Uni findByUserName(String userName) {
- return find("userName", userName).firstResult();
+ public static Uni findByUsername(String username) {
+ return find("username", username).firstResult();
}
}
diff --git a/integration-tests/security-webauthn/src/main/java/io/quarkus/it/security/webauthn/WebAuthnCredential.java b/integration-tests/security-webauthn/src/main/java/io/quarkus/it/security/webauthn/WebAuthnCredential.java
index ec0e526b9d9f0..6350f735ea63e 100644
--- a/integration-tests/security-webauthn/src/main/java/io/quarkus/it/security/webauthn/WebAuthnCredential.java
+++ b/integration-tests/security-webauthn/src/main/java/io/quarkus/it/security/webauthn/WebAuthnCredential.java
@@ -56,11 +56,11 @@ public WebAuthnCredential(WebAuthnCredentialRecord credentialRecord, User user)
public WebAuthnCredentialRecord toWebAuthnCredentialRecord() {
return WebAuthnCredentialRecord
.fromRequiredPersistedData(
- new RequiredPersistedData(user.userName, credID, aaguid, publicKey, publicKeyAlgorithm, counter));
+ new RequiredPersistedData(user.username, credID, aaguid, publicKey, publicKeyAlgorithm, counter));
}
- public static Uni> findByUserName(String userName) {
- return list("user.userName", userName);
+ public static Uni> findByUsername(String username) {
+ return list("user.username", username);
}
public static Uni findByCredentialId(String credID) {
diff --git a/integration-tests/security-webauthn/src/main/resources/META-INF/resources/index.html b/integration-tests/security-webauthn/src/main/resources/META-INF/resources/index.html
index 9446fd7df2d2f..293743f5c0257 100644
--- a/integration-tests/security-webauthn/src/main/resources/META-INF/resources/index.html
+++ b/integration-tests/security-webauthn/src/main/resources/META-INF/resources/index.html
@@ -57,14 +57,14 @@