@multiplatform.one/wallet 7.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/README.md +8 -0
  2. package/dist/cjs/SiweKeycloakProvider.cjs +273 -0
  3. package/dist/cjs/SiweKeycloakProvider.native.js +309 -0
  4. package/dist/cjs/SiweKeycloakProvider.native.js.map +1 -0
  5. package/dist/cjs/base64.cjs +51 -0
  6. package/dist/cjs/base64.native.js +55 -0
  7. package/dist/cjs/base64.native.js.map +1 -0
  8. package/dist/cjs/base64.spec.cjs +57 -0
  9. package/dist/cjs/base64.spec.native.js +79 -0
  10. package/dist/cjs/base64.spec.native.js.map +1 -0
  11. package/dist/cjs/context.cjs +29 -0
  12. package/dist/cjs/context.native.js +32 -0
  13. package/dist/cjs/context.native.js.map +1 -0
  14. package/dist/cjs/hooks/context.cjs +29 -0
  15. package/dist/cjs/hooks/context.native.js +32 -0
  16. package/dist/cjs/hooks/context.native.js.map +1 -0
  17. package/dist/cjs/hooks/index.cjs +20 -0
  18. package/dist/cjs/hooks/index.native.js +23 -0
  19. package/dist/cjs/hooks/index.native.js.map +1 -0
  20. package/dist/cjs/hooks/useSiweKeycloak.cjs +61 -0
  21. package/dist/cjs/hooks/useSiweKeycloak.native.js +64 -0
  22. package/dist/cjs/hooks/useSiweKeycloak.native.js.map +1 -0
  23. package/dist/cjs/index.cjs +133 -0
  24. package/dist/cjs/index.native.js +189 -0
  25. package/dist/cjs/index.native.js.map +1 -0
  26. package/dist/cjs/render.cjs +78 -0
  27. package/dist/cjs/render.native.js +82 -0
  28. package/dist/cjs/render.native.js.map +1 -0
  29. package/dist/cjs/siwe.cjs +76 -0
  30. package/dist/cjs/siwe.native.js +94 -0
  31. package/dist/cjs/siwe.native.js.map +1 -0
  32. package/dist/cjs/types.cjs +18 -0
  33. package/dist/cjs/types.native.js +21 -0
  34. package/dist/cjs/types.native.js.map +1 -0
  35. package/dist/cjs/util.cjs +53 -0
  36. package/dist/cjs/util.native.js +56 -0
  37. package/dist/cjs/util.native.js.map +1 -0
  38. package/dist/cjs/util.spec.cjs +53 -0
  39. package/dist/cjs/util.spec.native.js +62 -0
  40. package/dist/cjs/util.spec.native.js.map +1 -0
  41. package/dist/esm/SiweKeycloakProvider.mjs +237 -0
  42. package/dist/esm/SiweKeycloakProvider.mjs.map +1 -0
  43. package/dist/esm/SiweKeycloakProvider.native.js +270 -0
  44. package/dist/esm/SiweKeycloakProvider.native.js.map +1 -0
  45. package/dist/esm/base64.mjs +26 -0
  46. package/dist/esm/base64.mjs.map +1 -0
  47. package/dist/esm/base64.native.js +27 -0
  48. package/dist/esm/base64.native.js.map +1 -0
  49. package/dist/esm/base64.spec.mjs +58 -0
  50. package/dist/esm/base64.spec.mjs.map +1 -0
  51. package/dist/esm/base64.spec.native.js +77 -0
  52. package/dist/esm/base64.spec.native.js.map +1 -0
  53. package/dist/esm/context.mjs +4 -0
  54. package/dist/esm/context.mjs.map +1 -0
  55. package/dist/esm/context.native.js +4 -0
  56. package/dist/esm/context.native.js.map +1 -0
  57. package/dist/esm/hooks/context.mjs +4 -0
  58. package/dist/esm/hooks/context.mjs.map +1 -0
  59. package/dist/esm/hooks/context.native.js +4 -0
  60. package/dist/esm/hooks/context.native.js.map +1 -0
  61. package/dist/esm/hooks/index.mjs +2 -0
  62. package/dist/esm/hooks/index.mjs.map +1 -0
  63. package/dist/esm/hooks/index.native.js +2 -0
  64. package/dist/esm/hooks/index.native.js.map +1 -0
  65. package/dist/esm/hooks/useSiweKeycloak.mjs +36 -0
  66. package/dist/esm/hooks/useSiweKeycloak.mjs.map +1 -0
  67. package/dist/esm/hooks/useSiweKeycloak.native.js +36 -0
  68. package/dist/esm/hooks/useSiweKeycloak.native.js.map +1 -0
  69. package/dist/esm/index.mjs +107 -0
  70. package/dist/esm/index.mjs.map +1 -0
  71. package/dist/esm/index.native.js +160 -0
  72. package/dist/esm/index.native.js.map +1 -0
  73. package/dist/esm/render.mjs +42 -0
  74. package/dist/esm/render.mjs.map +1 -0
  75. package/dist/esm/render.native.js +43 -0
  76. package/dist/esm/render.native.js.map +1 -0
  77. package/dist/esm/siwe.mjs +51 -0
  78. package/dist/esm/siwe.mjs.map +1 -0
  79. package/dist/esm/siwe.native.js +66 -0
  80. package/dist/esm/siwe.native.js.map +1 -0
  81. package/dist/esm/types.mjs +2 -0
  82. package/dist/esm/types.mjs.map +1 -0
  83. package/dist/esm/types.native.js +2 -0
  84. package/dist/esm/types.native.js.map +1 -0
  85. package/dist/esm/util.mjs +27 -0
  86. package/dist/esm/util.mjs.map +1 -0
  87. package/dist/esm/util.native.js +27 -0
  88. package/dist/esm/util.native.js.map +1 -0
  89. package/dist/esm/util.spec.mjs +54 -0
  90. package/dist/esm/util.spec.mjs.map +1 -0
  91. package/dist/esm/util.spec.native.js +60 -0
  92. package/dist/esm/util.spec.native.js.map +1 -0
  93. package/package.json +81 -0
  94. package/src/SiweKeycloakProvider.tsx +297 -0
  95. package/src/base64.spec.ts +65 -0
  96. package/src/base64.ts +26 -0
  97. package/src/context.ts +10 -0
  98. package/src/hooks/context.ts +10 -0
  99. package/src/hooks/index.ts +1 -0
  100. package/src/hooks/useSiweKeycloak.ts +23 -0
  101. package/src/index.ts +127 -0
  102. package/src/main/java/com/bitspur/keycloak/siwe/Errors.java +21 -0
  103. package/src/main/java/com/bitspur/keycloak/siwe/LiteAuthenticationService.java +167 -0
  104. package/src/main/java/com/bitspur/keycloak/siwe/SiweCredentials.java +36 -0
  105. package/src/main/java/com/bitspur/keycloak/siwe/SiweSession.java +36 -0
  106. package/src/main/java/com/bitspur/keycloak/siwe/SiweUtil.java +599 -0
  107. package/src/main/java/com/bitspur/keycloak/siwe/Token.java +85 -0
  108. package/src/main/java/com/bitspur/keycloak/siwe/authenticators/browser/SiweBrowserAuthenticator.java +109 -0
  109. package/src/main/java/com/bitspur/keycloak/siwe/authenticators/browser/SiweBrowserAuthenticatorFactory.java +93 -0
  110. package/src/main/java/com/bitspur/keycloak/siwe/authenticators/directgrant/SiweDirectGrantAuthenticator.java +153 -0
  111. package/src/main/java/com/bitspur/keycloak/siwe/authenticators/directgrant/SiweDirectGrantAuthenticatorFactory.java +93 -0
  112. package/src/main/java/com/bitspur/keycloak/siwe/jpa/nonce/SiweNonce.java +95 -0
  113. package/src/main/java/com/bitspur/keycloak/siwe/jpa/nonce/SiweNonceJpaEntityProvider.java +82 -0
  114. package/src/main/java/com/bitspur/keycloak/siwe/jpa/nonce/SiweNonceJpaEntityProviderFactory.java +46 -0
  115. package/src/main/java/com/bitspur/keycloak/siwe/jpa/wallet/SiweWalletAddress.java +103 -0
  116. package/src/main/java/com/bitspur/keycloak/siwe/jpa/wallet/SiweWalletJpaEntityProvider.java +43 -0
  117. package/src/main/java/com/bitspur/keycloak/siwe/jpa/wallet/SiweWalletJpaEntityProviderFactory.java +46 -0
  118. package/src/main/java/com/bitspur/keycloak/siwe/protocol/SiweWalletProtocolMapper.java +85 -0
  119. package/src/main/java/com/bitspur/keycloak/siwe/resource/SiweResource.java +210 -0
  120. package/src/main/java/com/bitspur/keycloak/siwe/resource/SiweResourceProvider.java +34 -0
  121. package/src/main/java/com/bitspur/keycloak/siwe/resource/SiweResourceProviderFactory.java +46 -0
  122. package/src/main/java/com/bitspur/keycloak/siwe/siu/SiuCredentials.java +52 -0
  123. package/src/main/java/com/bitspur/keycloak/siwe/siu/SiuMessage.java +362 -0
  124. package/src/main/java/com/bitspur/keycloak/siwe/siu/SiuParseException.java +23 -0
  125. package/src/main/java/com/bitspur/keycloak/siwe/siu/SiuUtil.java +547 -0
  126. package/src/main/java/com/bitspur/keycloak/siwe/siu/authenticators/browser/SiuBrowserAuthenticator.java +112 -0
  127. package/src/main/java/com/bitspur/keycloak/siwe/siu/authenticators/browser/SiuBrowserAuthenticatorFactory.java +96 -0
  128. package/src/main/java/com/bitspur/keycloak/siwe/siu/authenticators/directgrant/SiuDirectGrantAuthenticator.java +169 -0
  129. package/src/main/java/com/bitspur/keycloak/siwe/siu/authenticators/directgrant/SiuDirectGrantAuthenticatorFactory.java +96 -0
  130. package/src/main/java/com/bitspur/keycloak/siwe/siu/resource/SiuResource.java +244 -0
  131. package/src/main/java/com/bitspur/keycloak/siwe/siu/resource/SiuResourceProvider.java +34 -0
  132. package/src/main/java/com/bitspur/keycloak/siwe/siu/resource/SiuResourceProviderFactory.java +48 -0
  133. package/src/main/java/com/bitspur/keycloak/siwe/siws/SiwsCredentials.java +52 -0
  134. package/src/main/java/com/bitspur/keycloak/siwe/siws/SiwsMessage.java +362 -0
  135. package/src/main/java/com/bitspur/keycloak/siwe/siws/SiwsParseException.java +23 -0
  136. package/src/main/java/com/bitspur/keycloak/siwe/siws/SiwsUtil.java +564 -0
  137. package/src/main/java/com/bitspur/keycloak/siwe/siws/authenticators/browser/SiwsBrowserAuthenticator.java +112 -0
  138. package/src/main/java/com/bitspur/keycloak/siwe/siws/authenticators/browser/SiwsBrowserAuthenticatorFactory.java +96 -0
  139. package/src/main/java/com/bitspur/keycloak/siwe/siws/authenticators/directgrant/SiwsDirectGrantAuthenticator.java +169 -0
  140. package/src/main/java/com/bitspur/keycloak/siwe/siws/authenticators/directgrant/SiwsDirectGrantAuthenticatorFactory.java +96 -0
  141. package/src/main/java/com/bitspur/keycloak/siwe/siws/resource/SiwsResource.java +244 -0
  142. package/src/main/java/com/bitspur/keycloak/siwe/siws/resource/SiwsResourceProvider.java +34 -0
  143. package/src/main/java/com/bitspur/keycloak/siwe/siws/resource/SiwsResourceProviderFactory.java +48 -0
  144. package/src/main/resources/META-INF/keycloak-themes.json +8 -0
  145. package/src/main/resources/META-INF/services/org.keycloak.authentication.AuthenticatorFactory +6 -0
  146. package/src/main/resources/META-INF/services/org.keycloak.connections.jpa.entityprovider.JpaEntityProviderFactory +2 -0
  147. package/src/main/resources/META-INF/services/org.keycloak.protocol.ProtocolMapper +1 -0
  148. package/src/main/resources/META-INF/services/org.keycloak.services.resource.RealmResourceProviderFactory +3 -0
  149. package/src/main/resources/META-INF/siwe-nonce-changelog.xml +29 -0
  150. package/src/main/resources/META-INF/siwe-wallet-changelog.xml +46 -0
  151. package/src/render.tsx +47 -0
  152. package/src/siwe.tsx +57 -0
  153. package/src/types.ts +6 -0
  154. package/src/util.spec.ts +72 -0
  155. package/src/util.ts +28 -0
@@ -0,0 +1,109 @@
1
+ /**
2
+ * File: /src/main/java/com/bitspur/keycloak/siwe/authenticators/browser/SiweBrowserAuthenticator.java
3
+ * Project: browser
4
+ * File Created: 20-03-2022 02:51:33
5
+ * Author: Clay Risser
6
+ * -----
7
+ * Last Modified: 10-01-2025 00:06:46
8
+ * Modified By: Clay Risser
9
+ * -----
10
+ * BitSpur (c) Copyright 2022
11
+ */
12
+
13
+ package com.bitspur.keycloak.siwe.authenticators.browser;
14
+
15
+ import jakarta.ws.rs.core.MultivaluedMap;
16
+
17
+ import org.jboss.logging.Logger;
18
+ import org.keycloak.authentication.AuthenticationFlowContext;
19
+ import org.keycloak.authentication.AuthenticationFlowError;
20
+ import org.keycloak.authentication.authenticators.browser.AbstractUsernameFormAuthenticator;
21
+ import org.keycloak.events.Errors;
22
+ import org.keycloak.forms.login.LoginFormsProvider;
23
+ import org.keycloak.models.KeycloakSession;
24
+ import org.keycloak.models.RealmModel;
25
+ import org.keycloak.models.UserModel;
26
+ import org.keycloak.representations.idm.CredentialRepresentation;
27
+ import org.keycloak.services.managers.AuthenticationManager;
28
+
29
+ import com.bitspur.keycloak.siwe.SiweCredentials;
30
+ import com.bitspur.keycloak.siwe.SiweUtil;
31
+ import com.bitspur.keycloak.siwe.Errors.SiweKeycloakException;
32
+
33
+ public class SiweBrowserAuthenticator extends AbstractUsernameFormAuthenticator {
34
+ private static final Logger logger = Logger.getLogger(SiweBrowserAuthenticator.class);
35
+
36
+ @Override
37
+ public void authenticate(AuthenticationFlowContext context) {
38
+ LoginFormsProvider form = context.form();
39
+ context.challenge(SiweUtil.createLoginSiwePage(form));
40
+ }
41
+
42
+ @Override
43
+ public void action(AuthenticationFlowContext context) {
44
+ MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
45
+ if (formData.containsKey("cancel")) {
46
+ context.cancelLogin();
47
+ return;
48
+ }
49
+ String password = this.retrievePassword(context);
50
+ String username = this.retrieveUsername(context);
51
+ try {
52
+ SiweCredentials siweCredentials = new SiweCredentials(username, password);
53
+ UserModel user = SiweUtil.findOrCreateUser(context, siweCredentials);
54
+ if (user == null) {
55
+ return;
56
+ }
57
+ context.setUser(user);
58
+ if (!SiweUtil.verify(context.getSession(), context.getAuthenticatorConfig(), siweCredentials)) {
59
+ context.attempted();
60
+ return;
61
+ }
62
+ } catch (SiweKeycloakException e) {
63
+ context.getEvent().user(context.getUser());
64
+ context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
65
+ LoginFormsProvider form = context.form();
66
+ logger.error(e);
67
+ context.failureChallenge(AuthenticationFlowError.INVALID_CREDENTIALS,
68
+ SiweUtil.createLoginSiwePage(form));
69
+ return;
70
+ }
71
+ context.success();
72
+ }
73
+
74
+ @Override
75
+ public boolean requiresUser() {
76
+ return false;
77
+ }
78
+
79
+ @Override
80
+ public boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user) {
81
+ return true;
82
+ }
83
+
84
+ @Override
85
+ public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
86
+ }
87
+
88
+ @Override
89
+ public void close() {
90
+ }
91
+
92
+ protected String retrievePassword(AuthenticationFlowContext context) {
93
+ MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
94
+ String password = formData.getFirst(CredentialRepresentation.PASSWORD);
95
+ if (password == null) {
96
+ return null;
97
+ }
98
+ return password.trim();
99
+ }
100
+
101
+ protected String retrieveUsername(AuthenticationFlowContext context) {
102
+ MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
103
+ String username = formData.getFirst(AuthenticationManager.FORM_USERNAME);
104
+ if (username == null) {
105
+ return null;
106
+ }
107
+ return username.trim();
108
+ }
109
+ }
@@ -0,0 +1,93 @@
1
+ /**
2
+ * File: /src/main/java/com/bitspur/keycloak/siwe/authenticators/browser/SiweBrowserAuthenticatorFactory.java
3
+ * Project: browser
4
+ * File Created: 20-03-2022 02:51:14
5
+ * Author: Clay Risser
6
+ * -----
7
+ * Last Modified: 10-08-2023 16:34:52
8
+ * Modified By: Clay Risser
9
+ * -----
10
+ * BitSpur (c) Copyright 2022
11
+ */
12
+
13
+ package com.bitspur.keycloak.siwe.authenticators.browser;
14
+
15
+ import java.util.Arrays;
16
+ import java.util.List;
17
+
18
+ import org.keycloak.Config;
19
+ import org.keycloak.authentication.Authenticator;
20
+ import org.keycloak.authentication.AuthenticatorFactory;
21
+ import org.keycloak.models.AuthenticationExecutionModel;
22
+ import org.keycloak.models.KeycloakSession;
23
+ import org.keycloak.models.KeycloakSessionFactory;
24
+ import org.keycloak.provider.ProviderConfigProperty;
25
+
26
+ import com.bitspur.keycloak.siwe.SiweUtil;
27
+
28
+ public class SiweBrowserAuthenticatorFactory implements AuthenticatorFactory {
29
+ public static final String ID = "siwe-browser-authenticator";
30
+
31
+ @Override
32
+ public Authenticator create(KeycloakSession keycloakSession) {
33
+ return new SiweBrowserAuthenticator();
34
+ }
35
+
36
+ @Override
37
+ public String getDisplayType() {
38
+ return "Siwe Browser Authenticator";
39
+ }
40
+
41
+ @Override
42
+ public boolean isConfigurable() {
43
+ return true;
44
+ }
45
+
46
+ @Override
47
+ public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
48
+ return new AuthenticationExecutionModel.Requirement[] {
49
+ AuthenticationExecutionModel.Requirement.REQUIRED,
50
+ AuthenticationExecutionModel.Requirement.ALTERNATIVE,
51
+ AuthenticationExecutionModel.Requirement.DISABLED,
52
+ };
53
+ }
54
+
55
+ @Override
56
+ public boolean isUserSetupAllowed() {
57
+ return false;
58
+ }
59
+
60
+ @Override
61
+ public String getHelpText() {
62
+ return "";
63
+ }
64
+
65
+ @Override
66
+ public List<ProviderConfigProperty> getConfigProperties() {
67
+ return Arrays.asList(
68
+ SiweUtil.getJsonRpcUrlConfigProperty(),
69
+ SiweUtil.getRequiredTokensConfigProperty());
70
+ }
71
+
72
+ @Override
73
+ public String getReferenceCategory() {
74
+ return null;
75
+ }
76
+
77
+ @Override
78
+ public void init(Config.Scope scope) {
79
+ }
80
+
81
+ @Override
82
+ public void postInit(KeycloakSessionFactory keycloakSessionFactory) {
83
+ }
84
+
85
+ @Override
86
+ public void close() {
87
+ }
88
+
89
+ @Override
90
+ public String getId() {
91
+ return SiweBrowserAuthenticatorFactory.ID;
92
+ }
93
+ }
@@ -0,0 +1,153 @@
1
+ /**
2
+ * File: /src/main/java/com/bitspur/keycloak/siwe/authenticators/directgrant/SiweDirectGrantAuthenticator.java
3
+ * Project: directgrant
4
+ * File Created: 21-03-2022 09:50:11
5
+ * Author: Clay Risser
6
+ * -----
7
+ * Last Modified: 09-01-2025 23:48:08
8
+ * Modified By: Clay Risser
9
+ * -----
10
+ * BitSpur (c) Copyright 2022
11
+ */
12
+
13
+ package com.bitspur.keycloak.siwe.authenticators.directgrant;
14
+
15
+ import jakarta.ws.rs.core.MediaType;
16
+ import jakarta.ws.rs.core.MultivaluedMap;
17
+ import jakarta.ws.rs.core.Response;
18
+
19
+ import static org.keycloak.authentication.authenticators.util.AuthenticatorUtils.getDisabledByBruteForceEventError;
20
+
21
+ import org.jboss.logging.Logger;
22
+ import org.keycloak.authentication.AuthenticationFlowContext;
23
+ import org.keycloak.authentication.AuthenticationFlowError;
24
+ import org.keycloak.authentication.Authenticator;
25
+ import org.keycloak.authentication.authenticators.browser.AbstractUsernameFormAuthenticator;
26
+ import org.keycloak.events.Details;
27
+ import org.keycloak.events.Errors;
28
+ import org.keycloak.http.HttpRequest;
29
+ import org.keycloak.models.KeycloakSession;
30
+ import org.keycloak.models.RealmModel;
31
+ import org.keycloak.models.UserModel;
32
+ import org.keycloak.representations.idm.CredentialRepresentation;
33
+ import org.keycloak.representations.idm.OAuth2ErrorRepresentation;
34
+ import org.keycloak.services.managers.AuthenticationManager;
35
+
36
+ import com.bitspur.keycloak.siwe.SiweCredentials;
37
+ import com.bitspur.keycloak.siwe.SiweUtil;
38
+ import com.bitspur.keycloak.siwe.Errors.SiweKeycloakException;;
39
+
40
+ public class SiweDirectGrantAuthenticator implements Authenticator {
41
+
42
+ Logger logger = Logger.getLogger(SiweDirectGrantAuthenticator.class);
43
+
44
+ @Override
45
+ public void authenticate(AuthenticationFlowContext context) {
46
+ String password = retrievePassword(context);
47
+ String username = retrieveUsername(context);
48
+ KeycloakSession session = context.getSession();
49
+ RealmModel realm = context.getRealm();
50
+ if (username == null) {
51
+ context.getEvent().error(Errors.USER_NOT_FOUND);
52
+ Response challengeResponse = this.errorResponse(Response.Status.UNAUTHORIZED, "invalid_request",
53
+ "Missing parameter: username");
54
+ context.failure(AuthenticationFlowError.INVALID_USER, challengeResponse);
55
+ return;
56
+ }
57
+ try {
58
+ SiweCredentials siweCredentials = new SiweCredentials(username, password);
59
+ String address = siweCredentials.message.getAddress();
60
+ context.getEvent().detail(Details.USERNAME, address);
61
+ context.getAuthenticationSession().setAuthNote(AbstractUsernameFormAuthenticator.ATTEMPTED_USERNAME, address);
62
+ UserModel user = SiweUtil.findOrCreateUser(context, siweCredentials, false);
63
+ if (user == null) {
64
+ context.getEvent().error(Errors.USER_NOT_FOUND);
65
+ Response challengeResponse = this.errorResponse(Response.Status.UNAUTHORIZED, "invalid_grant",
66
+ "Invalid user credentials");
67
+ context.failure(AuthenticationFlowError.INVALID_USER, challengeResponse);
68
+ return;
69
+ }
70
+ String bruteForceError = getDisabledByBruteForceEventError(context.getProtector(), session, realm, user);
71
+ if (bruteForceError != null) {
72
+ context.getEvent().user(user);
73
+ context.getEvent().error(bruteForceError);
74
+ Response challengeResponse = this.errorResponse(Response.Status.UNAUTHORIZED, "invalid_grant",
75
+ "Invalid user credentials");
76
+ context.forceChallenge(challengeResponse);
77
+ return;
78
+ }
79
+ if (!user.isEnabled()) {
80
+ context.getEvent().user(user);
81
+ context.getEvent().error(Errors.USER_DISABLED);
82
+ Response challengeResponse = this.errorResponse(Response.Status.BAD_REQUEST, "invalid_grant",
83
+ "Account disabled");
84
+ context.forceChallenge(challengeResponse);
85
+ return;
86
+ }
87
+ context.setUser(user);
88
+ if (!SiweUtil.verify(context.getSession(), context.getAuthenticatorConfig(), siweCredentials)) {
89
+ context.getEvent().user(context.getUser());
90
+ context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
91
+ Response challengeResponse = this.errorResponse(Response.Status.UNAUTHORIZED, "invalid_grant",
92
+ "Invalid user credentials");
93
+ context.failure(AuthenticationFlowError.INVALID_CREDENTIALS, challengeResponse);
94
+ return;
95
+ }
96
+ } catch (SiweKeycloakException e) {
97
+ logger.error(e);
98
+ context.getEvent().user(context.getUser());
99
+ context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
100
+ Response challengeResponse = this.errorResponse(Response.Status.UNAUTHORIZED, "invalid_grant",
101
+ e.getMessage());
102
+ context.failure(AuthenticationFlowError.INVALID_CREDENTIALS, challengeResponse);
103
+ return;
104
+ }
105
+ context.success();
106
+ }
107
+
108
+ @Override
109
+ public void action(AuthenticationFlowContext context) {
110
+ }
111
+
112
+ @Override
113
+ public boolean requiresUser() {
114
+ return false;
115
+ }
116
+
117
+ @Override
118
+ public boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user) {
119
+ return true;
120
+ }
121
+
122
+ @Override
123
+ public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {
124
+ }
125
+
126
+ @Override
127
+ public void close() {
128
+ }
129
+
130
+ protected String retrieveUsername(AuthenticationFlowContext context) {
131
+ HttpRequest request = context.getHttpRequest();
132
+ MultivaluedMap<String, String> formData = request.getDecodedFormParameters();
133
+ String username = formData.getFirst(AuthenticationManager.FORM_USERNAME);
134
+ if (username == null) {
135
+ return null;
136
+ }
137
+ return username.trim();
138
+ }
139
+
140
+ protected String retrievePassword(AuthenticationFlowContext context) {
141
+ MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
142
+ String password = formData.getFirst(CredentialRepresentation.PASSWORD);
143
+ if (password == null) {
144
+ return null;
145
+ }
146
+ return password.trim();
147
+ }
148
+
149
+ protected Response errorResponse(Response.Status status, String error, String errorDescription) {
150
+ OAuth2ErrorRepresentation errorRep = new OAuth2ErrorRepresentation(error, errorDescription);
151
+ return Response.status(status).entity(errorRep).type(MediaType.APPLICATION_JSON_TYPE).build();
152
+ }
153
+ }
@@ -0,0 +1,93 @@
1
+ /**
2
+ * File: /src/main/java/com/bitspur/keycloak/siwe/authenticators/directgrant/SiweDirectGrantAuthenticatorFactory.java
3
+ * Project: directgrant
4
+ * File Created: 21-03-2022 09:50:49
5
+ * Author: Clay Risser
6
+ * -----
7
+ * Last Modified: 10-08-2023 16:34:52
8
+ * Modified By: Clay Risser
9
+ * -----
10
+ * BitSpur (c) Copyright 2022
11
+ */
12
+
13
+ package com.bitspur.keycloak.siwe.authenticators.directgrant;
14
+
15
+ import java.util.Arrays;
16
+ import java.util.List;
17
+
18
+ import org.keycloak.Config;
19
+ import org.keycloak.authentication.Authenticator;
20
+ import org.keycloak.authentication.AuthenticatorFactory;
21
+ import org.keycloak.models.AuthenticationExecutionModel;
22
+ import org.keycloak.models.KeycloakSession;
23
+ import org.keycloak.models.KeycloakSessionFactory;
24
+ import org.keycloak.provider.ProviderConfigProperty;
25
+
26
+ import com.bitspur.keycloak.siwe.SiweUtil;
27
+
28
+ public class SiweDirectGrantAuthenticatorFactory implements AuthenticatorFactory {
29
+ public static final String ID = "siwe-direct-grant-authenticator";
30
+
31
+ @Override
32
+ public Authenticator create(KeycloakSession keycloakSession) {
33
+ return new SiweDirectGrantAuthenticator();
34
+ }
35
+
36
+ @Override
37
+ public String getDisplayType() {
38
+ return "Siwe Direct Grant Authenticator";
39
+ }
40
+
41
+ @Override
42
+ public boolean isConfigurable() {
43
+ return true;
44
+ }
45
+
46
+ @Override
47
+ public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
48
+ return new AuthenticationExecutionModel.Requirement[] {
49
+ AuthenticationExecutionModel.Requirement.REQUIRED,
50
+ AuthenticationExecutionModel.Requirement.ALTERNATIVE,
51
+ AuthenticationExecutionModel.Requirement.DISABLED,
52
+ };
53
+ }
54
+
55
+ @Override
56
+ public boolean isUserSetupAllowed() {
57
+ return false;
58
+ }
59
+
60
+ @Override
61
+ public String getHelpText() {
62
+ return "";
63
+ }
64
+
65
+ @Override
66
+ public List<ProviderConfigProperty> getConfigProperties() {
67
+ return Arrays.asList(
68
+ SiweUtil.getJsonRpcUrlConfigProperty(),
69
+ SiweUtil.getRequiredTokensConfigProperty());
70
+ }
71
+
72
+ @Override
73
+ public String getReferenceCategory() {
74
+ return null;
75
+ }
76
+
77
+ @Override
78
+ public void init(Config.Scope scope) {
79
+ }
80
+
81
+ @Override
82
+ public void postInit(KeycloakSessionFactory keycloakSessionFactory) {
83
+ }
84
+
85
+ @Override
86
+ public void close() {
87
+ }
88
+
89
+ @Override
90
+ public String getId() {
91
+ return ID;
92
+ }
93
+ }
@@ -0,0 +1,95 @@
1
+ /**
2
+ * File: /src/main/java/com/bitspur/keycloak/siwe/jpa/nonce/SiweNonce.java
3
+ * Project: jpa
4
+ * File Created: 09-04-2023 10:40:57
5
+ * Author: Clay Risser
6
+ * -----
7
+ * Last Modified: 12-02-2024 12:32:34
8
+ * Modified By: Clay Risser
9
+ * -----
10
+ * BitSpur (c) Copyright 2022 - 2023
11
+ */
12
+
13
+ package com.bitspur.keycloak.siwe.jpa.nonce;
14
+
15
+ import java.time.LocalDateTime;
16
+
17
+ import jakarta.persistence.Column;
18
+ import jakarta.persistence.Entity;
19
+ import jakarta.persistence.GeneratedValue;
20
+ import jakarta.persistence.GenerationType;
21
+ import jakarta.persistence.Id;
22
+ import jakarta.persistence.NamedQueries;
23
+ import jakarta.persistence.NamedQuery;
24
+ import jakarta.persistence.Table;
25
+
26
+ import org.hibernate.annotations.CreationTimestamp;
27
+ import org.hibernate.annotations.UpdateTimestamp;
28
+
29
+ @Entity
30
+ @Table(name = "SIWE_NONCE")
31
+ @NamedQueries({
32
+ @NamedQuery(name = "findByRealm", query = "from SiweNonce where realmId = :realmId"),
33
+ @NamedQuery(name = "findByKey", query = "from SiweNonce where key = :key"),
34
+ @NamedQuery(name = "findByRealmKey", query = "from SiweNonce where realmId = :realmId and key = :key"),
35
+ @NamedQuery(name = "findOlderThan", query = "from SiweNonce where createdAt < :createdAt")
36
+ })
37
+ public class SiweNonce {
38
+ @Id
39
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
40
+ @Column(name = "ID", nullable = false)
41
+ private Long id;
42
+
43
+ @Column(name = "NONCE_KEY", nullable = false)
44
+ private String key;
45
+
46
+ @Column(name = "NONCE", nullable = true)
47
+ private String nonce;
48
+
49
+ @Column(name = "REALM_ID", nullable = false)
50
+ private String realmId;
51
+
52
+ @CreationTimestamp
53
+ @Column(name = "CREATED_AT", nullable = false, updatable = false)
54
+ private LocalDateTime createdAt;
55
+
56
+ @UpdateTimestamp
57
+ @Column(name = "UPDATED_AT", nullable = false)
58
+ private LocalDateTime updatedAt;
59
+
60
+ public Long getId() {
61
+ return this.id;
62
+ }
63
+
64
+ public String getKey() {
65
+ return this.key;
66
+ }
67
+
68
+ public String getNonce() {
69
+ return this.nonce;
70
+ }
71
+
72
+ public String getRealmId() {
73
+ return this.realmId;
74
+ }
75
+
76
+ public LocalDateTime getCreatedAt() {
77
+ return this.createdAt;
78
+ }
79
+
80
+ public LocalDateTime getUpdatedAt() {
81
+ return this.updatedAt;
82
+ }
83
+
84
+ public void setKey(String key) {
85
+ this.key = key;
86
+ }
87
+
88
+ public void setNonce(String nonce) {
89
+ this.nonce = nonce;
90
+ }
91
+
92
+ public void setRealmId(String realmId) {
93
+ this.realmId = realmId;
94
+ }
95
+ }
@@ -0,0 +1,82 @@
1
+
2
+ /**
3
+ * File: /src/main/java/com/bitspur/keycloak/siwe/jpa/nonce/SiweNonceJpaEntityProvider.java
4
+ * Project: authenticators
5
+ * File Created: 09-04-2023 10:30:42
6
+ * Author: Clay Risser
7
+ * -----
8
+ * Last Modified: 12-02-2024 12:33:17
9
+ * Modified By: Clay Risser
10
+ * -----
11
+ * BitSpur (c) Copyright 2022 - 2023
12
+ */
13
+
14
+ package com.bitspur.keycloak.siwe.jpa.nonce;
15
+
16
+ import org.jboss.logging.Logger;
17
+ import org.keycloak.connections.jpa.JpaConnectionProvider;
18
+ import org.keycloak.connections.jpa.entityprovider.JpaEntityProvider;
19
+ import org.keycloak.models.KeycloakSession;
20
+ import org.keycloak.services.scheduled.ScheduledTaskRunner;
21
+ import org.keycloak.timer.ScheduledTask;
22
+ import org.keycloak.timer.TimerProvider;
23
+
24
+ import java.time.Duration;
25
+ import java.time.LocalDateTime;
26
+ import java.util.Collections;
27
+ import java.util.List;
28
+
29
+ import jakarta.persistence.EntityManager;
30
+
31
+ public class SiweNonceJpaEntityProvider implements JpaEntityProvider {
32
+ KeycloakSession session;
33
+ private final Logger logger = Logger.getLogger(SiweNonceJpaEntityProvider.class);
34
+
35
+ SiweNonceJpaEntityProvider(KeycloakSession session) {
36
+ this.session = session;
37
+ this.scheduleTask();
38
+ }
39
+
40
+ @Override
41
+ public List<Class<?>> getEntities() {
42
+ return Collections.<Class<?>>singletonList(SiweNonce.class);
43
+ }
44
+
45
+ @Override
46
+ public String getChangelogLocation() {
47
+ return "META-INF/siwe-nonce-changelog.xml";
48
+ }
49
+
50
+ @Override
51
+ public void close() {
52
+ }
53
+
54
+ @Override
55
+ public String getFactoryId() {
56
+ return SiweNonceJpaEntityProviderFactory.ID;
57
+ }
58
+
59
+ public void scheduleTask() {
60
+ TimerProvider timer = session.getProvider(TimerProvider.class);
61
+ ScheduledTask task = new ScheduledTask() {
62
+ public void run(KeycloakSession session) {
63
+ Integer removedCount = removeOlderThan(LocalDateTime.now().minus(Duration.ofMinutes(10)));
64
+ if (removedCount > 0) {
65
+ logger.info("Cleaned up " + removedCount + " nonces");
66
+ }
67
+ }
68
+ };
69
+ ScheduledTaskRunner runner = new ScheduledTaskRunner(session.getKeycloakSessionFactory(), task);
70
+ timer.schedule(runner, Duration.ofMinutes(5).toMillis(), "siwe-cleanup");
71
+ }
72
+
73
+ private Integer removeOlderThan(LocalDateTime createdAt) {
74
+ EntityManager entityManager = session.getProvider(JpaConnectionProvider.class).getEntityManager();
75
+ List<SiweNonce> nonces = entityManager.createNamedQuery("findOlderThan", SiweNonce.class)
76
+ .setParameter("createdAt", createdAt).getResultList();
77
+ for (SiweNonce nonce : nonces) {
78
+ entityManager.remove(nonce);
79
+ }
80
+ return nonces.size();
81
+ }
82
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * File: /src/main/java/com/bitspur/keycloak/siwe/jpa/nonce/SiweNonceJpaEntityProviderFactory.java
3
+ * Project: jpa
4
+ * File Created: 09-04-2023 10:33:19
5
+ * Author: Clay Risser
6
+ * -----
7
+ * Last Modified: 10-08-2023 16:34:52
8
+ * Modified By: Clay Risser
9
+ * -----
10
+ * BitSpur (c) Copyright 2022 - 2023
11
+ */
12
+
13
+ package com.bitspur.keycloak.siwe.jpa.nonce;
14
+
15
+ import org.keycloak.Config.Scope;
16
+ import org.keycloak.connections.jpa.entityprovider.JpaEntityProvider;
17
+ import org.keycloak.connections.jpa.entityprovider.JpaEntityProviderFactory;
18
+ import org.keycloak.models.KeycloakSession;
19
+ import org.keycloak.models.KeycloakSessionFactory;
20
+
21
+ public class SiweNonceJpaEntityProviderFactory implements JpaEntityProviderFactory {
22
+
23
+ protected static final String ID = "siwe-nonce-entity-provider";
24
+
25
+ @Override
26
+ public JpaEntityProvider create(KeycloakSession session) {
27
+ return new SiweNonceJpaEntityProvider(session);
28
+ }
29
+
30
+ @Override
31
+ public String getId() {
32
+ return ID;
33
+ }
34
+
35
+ @Override
36
+ public void init(Scope config) {
37
+ }
38
+
39
+ @Override
40
+ public void postInit(KeycloakSessionFactory factory) {
41
+ }
42
+
43
+ @Override
44
+ public void close() {
45
+ }
46
+ }