@@ -71,6 +71,8 @@ import code.api.util.ExampleValue
7171import code .api .util .ExampleValue .dynamicEntityResponseBodyExample
7272import net .liftweb .common .Box
7373
74+ import java .net .URLDecoder
75+ import java .nio .charset .StandardCharsets
7476import java .text .SimpleDateFormat
7577import java .util .UUID .randomUUID
7678import scala .collection .immutable .{List , Nil }
@@ -8754,10 +8756,12 @@ trait APIMethods600 {
87548756 postedData <- NewStyle .function.tryons(s " $InvalidJsonFormat The Json body should be the PostVerifyUserCredentialsJsonV600 " , 400 , callContext) {
87558757 json.extract[PostVerifyUserCredentialsJsonV600 ]
87568758 }
8759+ // Decode the provider in case it's URL-encoded (e.g., "http%3A%2F%2Fexample.com" -> "http://example.com")
8760+ decodedProvider = URLDecoder .decode(postedData.provider, StandardCharsets .UTF_8 )
87578761 // Validate credentials using the existing AuthUser mechanism
87588762
87598763 resourceUserIdBox =
8760- if (postedData.provider == Constant .localIdentityProvider || postedData.provider .isEmpty) {
8764+ if (decodedProvider == Constant .localIdentityProvider || decodedProvider .isEmpty) {
87618765 // Local provider: only check local credentials. No external fallback.
87628766 val result = code.model.dataAccess.AuthUser .getResourceUserId(
87638767 postedData.username, postedData.password, Constant .localIdentityProvider
@@ -8767,8 +8771,8 @@ trait APIMethods600 {
87678771 } else {
87688772 // External provider: validate via connector. Local DB stores a random UUID
87698773 // as password for external users, so getResourceUserId would always fail.
8770- if (LoginAttempt .userIsLocked(postedData.provider , postedData.username)) {
8771- logger.info(s " verifyUserCredentials says: external user is locked, provider: ${postedData.provider }, username: ${postedData.username}" )
8774+ if (LoginAttempt .userIsLocked(decodedProvider , postedData.username)) {
8775+ logger.info(s " verifyUserCredentials says: external user is locked, provider: ${decodedProvider }, username: ${postedData.username}" )
87728776 Full (code.model.dataAccess.AuthUser .usernameLockedStateCode)
87738777 } else {
87748778 val connectorResult = code.model.dataAccess.AuthUser .externalUserHelper(
@@ -8777,10 +8781,10 @@ trait APIMethods600 {
87778781 logger.info(s " verifyUserCredentials says: externalUserHelper result: $connectorResult" )
87788782 connectorResult match {
87798783 case Full (_) =>
8780- LoginAttempt .resetBadLoginAttempts(postedData.provider , postedData.username)
8784+ LoginAttempt .resetBadLoginAttempts(decodedProvider , postedData.username)
87818785 connectorResult
87828786 case _ =>
8783- LoginAttempt .incrementBadLoginAttempts(postedData.provider , postedData.username)
8787+ LoginAttempt .incrementBadLoginAttempts(decodedProvider , postedData.username)
87848788 connectorResult
87858789 }
87868790 }
@@ -8803,7 +8807,7 @@ trait APIMethods600 {
88038807 }
88048808 // Verify provider matches if specified and not empty
88058809 _ <- Helper .booleanToFuture(s " $InvalidLoginCredentials Authentication provider mismatch. " , 401 , callContext) {
8806- postedData.provider. isEmpty || user.provider == postedData.provider
8810+ decodedProvider. isEmpty || user.provider == decodedProvider
88078811 }
88088812 } yield {
88098813 (JSONFactory200 .createUserJSON(user), HttpCode .`200`(callContext))
0 commit comments