mirror of
https://github.com/wasp-lang/wasp.git
synced 2024-12-27 19:14:52 +03:00
Adds Keycloak OAuth provider (#1876)
This commit is contained in:
parent
3d5ed1a5d3
commit
0880556592
@ -182,6 +182,9 @@ studio = do
|
||||
[ "google"
|
||||
| isJust $ AS.App.Auth.google methods
|
||||
],
|
||||
[ "keycloak"
|
||||
| isJust $ AS.App.Auth.keycloak methods
|
||||
],
|
||||
[ "gitHub"
|
||||
| isJust $ AS.App.Auth.gitHub methods
|
||||
],
|
||||
|
@ -108,6 +108,9 @@ const SocialAuthButtons = styled('div', {
|
||||
{=# isGoogleAuthEnabled =}
|
||||
const googleSignInUrl = `${config.apiUrl}{= googleSignInPath =}`
|
||||
{=/ isGoogleAuthEnabled =}
|
||||
{=# isKeycloakAuthEnabled =}
|
||||
const keycloakSignInUrl = `${config.apiUrl}{= keycloakSignInPath =}`
|
||||
{=/ isKeycloakAuthEnabled =}
|
||||
{=# isGitHubAuthEnabled =}
|
||||
const gitHubSignInUrl = `${config.apiUrl}{= gitHubSignInPath =}`
|
||||
{=/ isGitHubAuthEnabled =}
|
||||
@ -192,6 +195,10 @@ export const LoginSignupForm = ({
|
||||
<SocialButton href={googleSignInUrl}><SocialIcons.Google/></SocialButton>
|
||||
{=/ isGoogleAuthEnabled =}
|
||||
|
||||
{=# isKeycloakAuthEnabled =}
|
||||
<SocialButton href={keycloakSignInUrl}><SocialIcons.Keycloak/></SocialButton>
|
||||
{=/ isKeycloakAuthEnabled =}
|
||||
|
||||
{=# isGitHubAuthEnabled =}
|
||||
<SocialButton href={gitHubSignInUrl}><SocialIcons.GitHub/></SocialButton>
|
||||
{=/ isGitHubAuthEnabled =}
|
||||
|
@ -24,6 +24,21 @@ export const Google = () => (
|
||||
</svg>
|
||||
)
|
||||
|
||||
export const Keycloak = () => (
|
||||
<svg
|
||||
className={defaultStyles()}
|
||||
aria-hidden="true"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 559 466"
|
||||
>
|
||||
<g id="brand" transform="matrix(1,0,0,1,-233.075,-279.1)" fill="#000000" fillRule="nonzero">
|
||||
<path
|
||||
d="M786.2,395.5L705.6,395.5C704.1,395.5 702.6,394.7 701.9,393.4L637.2,281.2C636.4,279.9 635,279.1 633.4,279.1L369.4,279.1C367.9,279.1 366.4,279.9 365.7,281.2L298.4,397.6L233.6,509.8C232.9,511.1 232.9,512.7 233.6,514.1L298.4,626.3L365.6,742.8C366.3,744.1 367.8,745 369.3,744.9L633.4,744.9C634.9,744.9 636.4,744.1 637.2,742.8L702,630.6C702.7,629.3 704.2,628.4 705.7,628.5L786.3,628.5C789,628.5 791.1,626.3 791.1,623.7L791.1,400.4C791,397.7 788.8,395.5 786.2,395.5ZM477.5,630.6L457.2,665.6C456.9,666.1 456.4,666.6 455.9,666.9C455.3,667.2 454.7,667.4 454,667.4L413.7,667.4C412.3,667.4 411,666.7 410.4,665.4L350.3,561.1L344.4,550.8L322.8,513.9C322.5,513.4 322.3,512.8 322.4,512.1C322.4,511.5 322.6,510.8 322.9,510.3L344.6,472.7L410.5,358.7C411.2,357.5 412.5,356.7 413.8,356.7L454,356.7C454.7,356.7 455.4,356.9 456.1,357.2C456.6,357.5 457.1,357.9 457.4,358.5L477.7,393.7C478.3,394.9 478.2,396.4 477.5,397.5L412.4,510.3C412.1,510.8 412,511.4 412,511.9C412,512.5 412.2,513 412.4,513.5L477.5,626.2C478.4,627.7 478.3,629.3 477.5,630.6ZM679.6,513.9L658,550.8L652.1,561.1L592,665.4C591.3,666.6 590.1,667.4 588.7,667.4L548.4,667.4C547.7,667.4 547.1,667.2 546.5,666.9C546,666.6 545.5,666.2 545.2,665.6L524.9,630.6C524,629.3 524,627.7 524.8,626.4L589.9,513.7C590.2,513.2 590.3,512.6 590.3,512.1C590.3,511.5 590.1,511 589.9,510.5L524.8,397.7C524.1,396.5 524,395.1 524.6,393.9L544.9,358.7C545.2,358.2 545.7,357.7 546.2,357.4C546.8,357 547.5,356.9 548.3,356.9L588.7,356.9C590.1,356.9 591.4,357.6 592,358.9L657.9,472.9L679.6,510.5C679.9,511.1 680.1,511.7 680.1,512.3C680.1,512.7 679.9,513.3 679.6,513.9Z"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
)
|
||||
|
||||
// PRIVATE API
|
||||
export const GitHub = () => (
|
||||
<svg
|
||||
|
@ -41,6 +41,7 @@ export type PossibleProviderData = {
|
||||
email: EmailProviderData;
|
||||
username: UsernameProviderData;
|
||||
google: OAuthProviderData;
|
||||
keycloak: OAuthProviderData;
|
||||
github: OAuthProviderData;
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,9 @@ export * from './username'
|
||||
{=# isGoogleAuthEnabled =}
|
||||
export * from './google'
|
||||
{=/ isGoogleAuthEnabled =}
|
||||
{=# isKeycloakAuthEnabled =}
|
||||
export * from './keycloak'
|
||||
{=/ isKeycloakAuthEnabled =}
|
||||
{=# isGitHubAuthEnabled =}
|
||||
export * from './github'
|
||||
{=/ isGitHubAuthEnabled =}
|
||||
|
@ -0,0 +1,2 @@
|
||||
// PUBLIC API
|
||||
export { signInUrl as keycloakSignInUrl } from '../../auth/helpers/Keycloak'
|
@ -0,0 +1,82 @@
|
||||
{{={= =}=}}
|
||||
import { Keycloak } from "arctic";
|
||||
|
||||
import type { ProviderConfig } from "wasp/auth/providers/types";
|
||||
import { getRedirectUriForCallback } from "../oauth/redirect.js";
|
||||
import { ensureEnvVarsForProvider } from "../oauth/env.js";
|
||||
import { mergeDefaultAndUserConfig } from "../oauth/config.js";
|
||||
import { createOAuthProviderRouter } from "../oauth/handler.js";
|
||||
|
||||
{=# userSignupFields.isDefined =}
|
||||
{=& userSignupFields.importStatement =}
|
||||
const _waspUserSignupFields = {= userSignupFields.importIdentifier =}
|
||||
{=/ userSignupFields.isDefined =}
|
||||
{=^ userSignupFields.isDefined =}
|
||||
const _waspUserSignupFields = undefined
|
||||
{=/ userSignupFields.isDefined =}
|
||||
{=# configFn.isDefined =}
|
||||
{=& configFn.importStatement =}
|
||||
const _waspUserDefinedConfigFn = {= configFn.importIdentifier =}
|
||||
{=/ configFn.isDefined =}
|
||||
{=^ configFn.isDefined =}
|
||||
const _waspUserDefinedConfigFn = undefined
|
||||
{=/ configFn.isDefined =}
|
||||
|
||||
const _waspConfig: ProviderConfig = {
|
||||
id: "{= providerId =}",
|
||||
displayName: "{= displayName =}",
|
||||
createRouter(provider) {
|
||||
const env = ensureEnvVarsForProvider(
|
||||
["KEYCLOAK_REALM_URL", "KEYCLOAK_CLIENT_ID", "KEYCLOAK_CLIENT_SECRET"],
|
||||
provider
|
||||
);
|
||||
|
||||
const keycloak = new Keycloak(
|
||||
env.KEYCLOAK_REALM_URL,
|
||||
env.KEYCLOAK_CLIENT_ID,
|
||||
env.KEYCLOAK_CLIENT_SECRET,
|
||||
getRedirectUriForCallback(provider.id).toString(),
|
||||
);
|
||||
|
||||
const config = mergeDefaultAndUserConfig({
|
||||
scopes: {=& requiredScopes =},
|
||||
}, _waspUserDefinedConfigFn);
|
||||
|
||||
async function getKeycloakProfile(accessToken: string): Promise<{
|
||||
providerProfile: unknown;
|
||||
providerUserId: string;
|
||||
}> {
|
||||
const userInfoEndpoint = `${env.KEYCLOAK_REALM_URL}/protocol/openid-connect/userinfo`;
|
||||
const response = await fetch(
|
||||
userInfoEndpoint,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
const providerProfile = (await response.json()) as {
|
||||
sub?: string;
|
||||
};
|
||||
|
||||
if (!providerProfile.sub) {
|
||||
throw new Error("Invalid profile");
|
||||
}
|
||||
|
||||
return { providerProfile, providerUserId: providerProfile.sub };
|
||||
}
|
||||
|
||||
return createOAuthProviderRouter({
|
||||
provider,
|
||||
stateTypes: ['state', 'codeVerifier'],
|
||||
userSignupFields: _waspUserSignupFields,
|
||||
getAuthorizationUrl: ({ state, codeVerifier }) => keycloak.createAuthorizationURL(state, codeVerifier, config),
|
||||
getProviderInfo: async ({ code, codeVerifier }) => {
|
||||
const { accessToken } = await keycloak.validateAuthorizationCode(code, codeVerifier);
|
||||
return getKeycloakProfile(accessToken);
|
||||
},
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
export default _waspConfig;
|
@ -37,6 +37,7 @@ export type PossibleProviderData = {
|
||||
email: EmailProviderData;
|
||||
username: UsernameProviderData;
|
||||
google: OAuthProviderData;
|
||||
keycloak: OAuthProviderData;
|
||||
github: OAuthProviderData;
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@
|
||||
"file",
|
||||
"../out/sdk/wasp/auth/forms/internal/common/LoginSignupForm.tsx"
|
||||
],
|
||||
"cba000c7dedb0e2f1c9730719e23215036a599bd58e7590adc5cdb176ac6b76b"
|
||||
"c3299b01607b1206208e3e24a2830932607e8783a660b51e8f9168cbb067aab1"
|
||||
],
|
||||
[
|
||||
[
|
||||
@ -67,7 +67,7 @@
|
||||
"file",
|
||||
"../out/sdk/wasp/auth/forms/internal/social/SocialIcons.tsx"
|
||||
],
|
||||
"bca4b3d9bc1cd57bdc83ad51be235ac5a5f220e8b63a91dcce6da296f32f51c6"
|
||||
"eb12637809476e963828a91896d260f10552c7dd8d7f48f113ca0bfcee7f9ef0"
|
||||
],
|
||||
[
|
||||
[
|
||||
@ -165,7 +165,7 @@
|
||||
"file",
|
||||
"../out/sdk/wasp/auth/utils.ts"
|
||||
],
|
||||
"014159c084202532b1da84bcd945f77960fe1f7acd383afc905e8fbea35b9d71"
|
||||
"4001e5179622ab1c71646ad4225136a16cb9e7df9890c4bfd767c481e86c7619"
|
||||
],
|
||||
[
|
||||
[
|
||||
|
@ -93,6 +93,7 @@ export const LoginSignupForm = ({
|
||||
<SocialAuthButtons gap='large' direction={socialButtonsDirection}>
|
||||
<SocialButton href={googleSignInUrl}><SocialIcons.Google/></SocialButton>
|
||||
|
||||
|
||||
</SocialAuthButtons>
|
||||
</SocialAuth>
|
||||
</>)
|
||||
|
@ -24,6 +24,21 @@ export const Google = () => (
|
||||
</svg>
|
||||
)
|
||||
|
||||
export const Keycloak = () => (
|
||||
<svg
|
||||
className={defaultStyles()}
|
||||
aria-hidden="true"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 559 466"
|
||||
>
|
||||
<g id="brand" transform="matrix(1,0,0,1,-233.075,-279.1)" fill="#000000" fillRule="nonzero">
|
||||
<path
|
||||
d="M786.2,395.5L705.6,395.5C704.1,395.5 702.6,394.7 701.9,393.4L637.2,281.2C636.4,279.9 635,279.1 633.4,279.1L369.4,279.1C367.9,279.1 366.4,279.9 365.7,281.2L298.4,397.6L233.6,509.8C232.9,511.1 232.9,512.7 233.6,514.1L298.4,626.3L365.6,742.8C366.3,744.1 367.8,745 369.3,744.9L633.4,744.9C634.9,744.9 636.4,744.1 637.2,742.8L702,630.6C702.7,629.3 704.2,628.4 705.7,628.5L786.3,628.5C789,628.5 791.1,626.3 791.1,623.7L791.1,400.4C791,397.7 788.8,395.5 786.2,395.5ZM477.5,630.6L457.2,665.6C456.9,666.1 456.4,666.6 455.9,666.9C455.3,667.2 454.7,667.4 454,667.4L413.7,667.4C412.3,667.4 411,666.7 410.4,665.4L350.3,561.1L344.4,550.8L322.8,513.9C322.5,513.4 322.3,512.8 322.4,512.1C322.4,511.5 322.6,510.8 322.9,510.3L344.6,472.7L410.5,358.7C411.2,357.5 412.5,356.7 413.8,356.7L454,356.7C454.7,356.7 455.4,356.9 456.1,357.2C456.6,357.5 457.1,357.9 457.4,358.5L477.7,393.7C478.3,394.9 478.2,396.4 477.5,397.5L412.4,510.3C412.1,510.8 412,511.4 412,511.9C412,512.5 412.2,513 412.4,513.5L477.5,626.2C478.4,627.7 478.3,629.3 477.5,630.6ZM679.6,513.9L658,550.8L652.1,561.1L592,665.4C591.3,666.6 590.1,667.4 588.7,667.4L548.4,667.4C547.7,667.4 547.1,667.2 546.5,666.9C546,666.6 545.5,666.2 545.2,665.6L524.9,630.6C524,629.3 524,627.7 524.8,626.4L589.9,513.7C590.2,513.2 590.3,512.6 590.3,512.1C590.3,511.5 590.1,511 589.9,510.5L524.8,397.7C524.1,396.5 524,395.1 524.6,393.9L544.9,358.7C545.2,358.2 545.7,357.7 546.2,357.4C546.8,357 547.5,356.9 548.3,356.9L588.7,356.9C590.1,356.9 591.4,357.6 592,358.9L657.9,472.9L679.6,510.5C679.9,511.1 680.1,511.7 680.1,512.3C680.1,512.7 679.9,513.3 679.6,513.9Z"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
)
|
||||
|
||||
// PRIVATE API
|
||||
export const GitHub = () => (
|
||||
<svg
|
||||
|
@ -40,6 +40,7 @@ export type PossibleProviderData = {
|
||||
email: EmailProviderData;
|
||||
username: UsernameProviderData;
|
||||
google: OAuthProviderData;
|
||||
keycloak: OAuthProviderData;
|
||||
github: OAuthProviderData;
|
||||
}
|
||||
|
||||
|
@ -54,6 +54,7 @@ export const LoginSignupForm = ({ state, socialButtonsDirection = 'horizontal',
|
||||
<SocialAuthButtons gap='large' direction={socialButtonsDirection}>
|
||||
<SocialButton href={googleSignInUrl}><SocialIcons.Google /></SocialButton>
|
||||
|
||||
|
||||
</SocialAuthButtons>
|
||||
</SocialAuth>
|
||||
</>);
|
||||
|
@ -1 +1 @@
|
||||
{"version":3,"file":"LoginSignupForm.jsx","sourceRoot":"","sources":["../../../../../auth/forms/internal/common/LoginSignupForm.tsx"],"names":[],"mappings":"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"}
|
||||
{"version":3,"file":"LoginSignupForm.jsx","sourceRoot":"","sources":["../../../../../auth/forms/internal/common/LoginSignupForm.tsx"],"names":[],"mappings":"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"}
|
@ -1,3 +1,4 @@
|
||||
/// <reference types="react" />
|
||||
export declare const Google: () => import("react").JSX.Element;
|
||||
export declare const Keycloak: () => import("react").JSX.Element;
|
||||
export declare const GitHub: () => import("react").JSX.Element;
|
||||
|
@ -11,6 +11,11 @@ export const Google = () => (<svg className={defaultStyles()} aria-hidden="true"
|
||||
</g>
|
||||
</g>
|
||||
</svg>);
|
||||
export const Keycloak = () => (<svg className={defaultStyles()} aria-hidden="true" fill="currentColor" viewBox="0 0 559 466">
|
||||
<g id="brand" transform="matrix(1,0,0,1,-233.075,-279.1)" fill="#000000" fillRule="nonzero">
|
||||
<path d="M786.2,395.5L705.6,395.5C704.1,395.5 702.6,394.7 701.9,393.4L637.2,281.2C636.4,279.9 635,279.1 633.4,279.1L369.4,279.1C367.9,279.1 366.4,279.9 365.7,281.2L298.4,397.6L233.6,509.8C232.9,511.1 232.9,512.7 233.6,514.1L298.4,626.3L365.6,742.8C366.3,744.1 367.8,745 369.3,744.9L633.4,744.9C634.9,744.9 636.4,744.1 637.2,742.8L702,630.6C702.7,629.3 704.2,628.4 705.7,628.5L786.3,628.5C789,628.5 791.1,626.3 791.1,623.7L791.1,400.4C791,397.7 788.8,395.5 786.2,395.5ZM477.5,630.6L457.2,665.6C456.9,666.1 456.4,666.6 455.9,666.9C455.3,667.2 454.7,667.4 454,667.4L413.7,667.4C412.3,667.4 411,666.7 410.4,665.4L350.3,561.1L344.4,550.8L322.8,513.9C322.5,513.4 322.3,512.8 322.4,512.1C322.4,511.5 322.6,510.8 322.9,510.3L344.6,472.7L410.5,358.7C411.2,357.5 412.5,356.7 413.8,356.7L454,356.7C454.7,356.7 455.4,356.9 456.1,357.2C456.6,357.5 457.1,357.9 457.4,358.5L477.7,393.7C478.3,394.9 478.2,396.4 477.5,397.5L412.4,510.3C412.1,510.8 412,511.4 412,511.9C412,512.5 412.2,513 412.4,513.5L477.5,626.2C478.4,627.7 478.3,629.3 477.5,630.6ZM679.6,513.9L658,550.8L652.1,561.1L592,665.4C591.3,666.6 590.1,667.4 588.7,667.4L548.4,667.4C547.7,667.4 547.1,667.2 546.5,666.9C546,666.6 545.5,666.2 545.2,665.6L524.9,630.6C524,629.3 524,627.7 524.8,626.4L589.9,513.7C590.2,513.2 590.3,512.6 590.3,512.1C590.3,511.5 590.1,511 589.9,510.5L524.8,397.7C524.1,396.5 524,395.1 524.6,393.9L544.9,358.7C545.2,358.2 545.7,357.7 546.2,357.4C546.8,357 547.5,356.9 548.3,356.9L588.7,356.9C590.1,356.9 591.4,357.6 592,358.9L657.9,472.9L679.6,510.5C679.9,511.1 680.1,511.7 680.1,512.3C680.1,512.7 679.9,513.3 679.6,513.9Z"/>
|
||||
</g>
|
||||
</svg>);
|
||||
// PRIVATE API
|
||||
export const GitHub = () => (<svg className={defaultStyles()} aria-hidden="true" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fillRule="evenodd" d="M10 0C4.477 0 0 4.484 0 10.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0110 4.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.203 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.942.359.31.678.921.678 1.856 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0020 10.017C20 4.484 15.522 0 10 0z" clipRule="evenodd"/>
|
||||
|
@ -1 +1 @@
|
||||
{"version":3,"file":"SocialIcons.jsx","sourceRoot":"","sources":["../../../../../auth/forms/internal/social/SocialIcons.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAA;AAErC,MAAM,aAAa,GAAG,GAAG,CAAC;IACxB,KAAK,EAAE,SAAS;IAChB,MAAM,EAAE,SAAS;CAClB,CAAC,CAAA;AAEF,cAAc;AACd,MAAM,CAAC,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC,CAC1B,CAAC,GAAG,CACF,SAAS,CAAC,CAAC,aAAa,EAAE,CAAC,CAC3B,WAAW,CAAC,MAAM,CAClB,IAAI,CAAC,cAAc,CACnB,OAAO,CAAC,WAAW,CAEnB;IAAA,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CACxE;MAAA,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,SAAS,CAC9C;QAAA,CAAC,IAAI,CACH,CAAC,CAAC,sVAAsV,CACxV,EAAE,CAAC,OAAO,CACX,EAAE,IAAI,CACT;MAAA,EAAE,CAAC,CACL;IAAA,EAAE,CAAC,CACL;EAAA,EAAE,GAAG,CAAC,CACP,CAAA;AAED,cAAc;AACd,MAAM,CAAC,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC,CAC1B,CAAC,GAAG,CACF,SAAS,CAAC,CAAC,aAAa,EAAE,CAAC,CAC3B,WAAW,CAAC,MAAM,CAClB,IAAI,CAAC,cAAc,CACnB,OAAO,CAAC,WAAW,CAEnB;IAAA,CAAC,IAAI,CACH,QAAQ,CAAC,SAAS,CAClB,CAAC,CAAC,ktBAAktB,CACptB,QAAQ,CAAC,SAAS,EAEtB;EAAA,EAAE,GAAG,CAAC,CACP,CAAA"}
|
||||
{"version":3,"file":"SocialIcons.jsx","sourceRoot":"","sources":["../../../../../auth/forms/internal/social/SocialIcons.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAA;AAErC,MAAM,aAAa,GAAG,GAAG,CAAC;IACxB,KAAK,EAAE,SAAS;IAChB,MAAM,EAAE,SAAS;CAClB,CAAC,CAAA;AAEF,cAAc;AACd,MAAM,CAAC,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC,CAC1B,CAAC,GAAG,CACF,SAAS,CAAC,CAAC,aAAa,EAAE,CAAC,CAC3B,WAAW,CAAC,MAAM,CAClB,IAAI,CAAC,cAAc,CACnB,OAAO,CAAC,WAAW,CAEnB;IAAA,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CACxE;MAAA,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,SAAS,CAC9C;QAAA,CAAC,IAAI,CACH,CAAC,CAAC,sVAAsV,CACxV,EAAE,CAAC,OAAO,CACX,EAAE,IAAI,CACT;MAAA,EAAE,CAAC,CACL;IAAA,EAAE,CAAC,CACL;EAAA,EAAE,GAAG,CAAC,CACP,CAAA;AAED,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAG,EAAE,CAAC,CAC5B,CAAC,GAAG,CACF,SAAS,CAAC,CAAC,aAAa,EAAE,CAAC,CAC3B,WAAW,CAAC,MAAM,CAClB,IAAI,CAAC,cAAc,CACnB,OAAO,CAAC,aAAa,CAErB;IAAA,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,iCAAiC,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,SAAS,CACzF;MAAA,CAAC,IAAI,CACH,CAAC,CAAC,+iDAA+iD,EAErjD;IAAA,EAAE,CAAC,CACL;EAAA,EAAE,GAAG,CAAC,CACP,CAAA;AAED,cAAc;AACd,MAAM,CAAC,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC,CAC1B,CAAC,GAAG,CACF,SAAS,CAAC,CAAC,aAAa,EAAE,CAAC,CAC3B,WAAW,CAAC,MAAM,CAClB,IAAI,CAAC,cAAc,CACnB,OAAO,CAAC,WAAW,CAEnB;IAAA,CAAC,IAAI,CACH,QAAQ,CAAC,SAAS,CAClB,CAAC,CAAC,ktBAAktB,CACptB,QAAQ,CAAC,SAAS,EAEtB;EAAA,EAAE,GAAG,CAAC,CACP,CAAA"}
|
@ -22,6 +22,7 @@ export type PossibleProviderData = {
|
||||
email: EmailProviderData;
|
||||
username: UsernameProviderData;
|
||||
google: OAuthProviderData;
|
||||
keycloak: OAuthProviderData;
|
||||
github: OAuthProviderData;
|
||||
};
|
||||
export type ProviderName = keyof PossibleProviderData;
|
||||
|
@ -1 +1 @@
|
||||
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../auth/utils.ts"],"names":[],"mappings":"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"}
|
||||
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../auth/utils.ts"],"names":[],"mappings":"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"}
|
@ -22,6 +22,7 @@ app todoApp {
|
||||
configFn: import { config } from "@src/auth/github.js",
|
||||
userSignupFields: import { userSignupFields } from "@src/auth/github.js"
|
||||
},
|
||||
keycloak: {},
|
||||
email: {
|
||||
userSignupFields: import { userSignupFields } from "@src/auth/email.js",
|
||||
fromField: {
|
||||
|
@ -21,6 +21,11 @@ export function getName(user?: User) {
|
||||
return `GitHub user ${githubIdentity.providerUserId}`
|
||||
}
|
||||
|
||||
const keycloakIdentity = findUserIdentity(user, 'keycloak')
|
||||
if (keycloakIdentity) {
|
||||
return `Keycloak user ${keycloakIdentity.providerUserId}`
|
||||
}
|
||||
|
||||
// If we don't know how to get the name, return null.
|
||||
return null
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ module Wasp.AppSpec.App.Auth
|
||||
isUsernameAndPasswordAuthEnabled,
|
||||
isExternalAuthEnabled,
|
||||
isGoogleAuthEnabled,
|
||||
isKeycloakAuthEnabled,
|
||||
isGitHubAuthEnabled,
|
||||
isEmailAuthEnabled,
|
||||
userSignupFieldsForEmailAuth,
|
||||
@ -40,6 +41,7 @@ data AuthMethods = AuthMethods
|
||||
{ usernameAndPassword :: Maybe UsernameAndPasswordConfig,
|
||||
google :: Maybe ExternalAuthConfig,
|
||||
gitHub :: Maybe ExternalAuthConfig,
|
||||
keycloak :: Maybe ExternalAuthConfig,
|
||||
email :: Maybe EmailAuthConfig
|
||||
}
|
||||
deriving (Show, Eq, Data)
|
||||
@ -67,11 +69,21 @@ isUsernameAndPasswordAuthEnabled :: Auth -> Bool
|
||||
isUsernameAndPasswordAuthEnabled = isJust . usernameAndPassword . methods
|
||||
|
||||
isExternalAuthEnabled :: Auth -> Bool
|
||||
isExternalAuthEnabled auth = any ($ auth) [isGoogleAuthEnabled, isGitHubAuthEnabled]
|
||||
isExternalAuthEnabled auth =
|
||||
any
|
||||
($ auth)
|
||||
-- NOTE: Make sure to add new external auth methods here.
|
||||
[ isGoogleAuthEnabled,
|
||||
isGitHubAuthEnabled,
|
||||
isKeycloakAuthEnabled
|
||||
]
|
||||
|
||||
isGoogleAuthEnabled :: Auth -> Bool
|
||||
isGoogleAuthEnabled = isJust . google . methods
|
||||
|
||||
isKeycloakAuthEnabled :: Auth -> Bool
|
||||
isKeycloakAuthEnabled = isJust . keycloak . methods
|
||||
|
||||
isGitHubAuthEnabled :: Auth -> Bool
|
||||
isGitHubAuthEnabled = isJust . gitHub . methods
|
||||
|
||||
|
@ -14,6 +14,14 @@ googleAuthProvider =
|
||||
OA._requiredScope = ["profile"]
|
||||
}
|
||||
|
||||
keycloakAuthProvider :: OA.OAuthAuthProvider
|
||||
keycloakAuthProvider =
|
||||
OA.OAuthAuthProvider
|
||||
{ OA._providerId = fromJust $ makeProviderId "keycloak",
|
||||
OA._displayName = "Keycloak",
|
||||
OA._requiredScope = ["profile"]
|
||||
}
|
||||
|
||||
gitHubAuthProvider :: OA.OAuthAuthProvider
|
||||
gitHubAuthProvider =
|
||||
OA.OAuthAuthProvider
|
||||
|
@ -6,7 +6,11 @@ where
|
||||
import Data.Aeson (object, (.=))
|
||||
import StrongPath (reldir, relfile, (</>))
|
||||
import qualified Wasp.AppSpec.App.Auth as AS.Auth
|
||||
import Wasp.Generator.AuthProviders (gitHubAuthProvider, googleAuthProvider)
|
||||
import Wasp.Generator.AuthProviders
|
||||
( gitHubAuthProvider,
|
||||
googleAuthProvider,
|
||||
keycloakAuthProvider,
|
||||
)
|
||||
import qualified Wasp.Generator.AuthProviders.OAuth as OAuth
|
||||
import Wasp.Generator.FileDraft (FileDraft)
|
||||
import Wasp.Generator.Monad (Generator)
|
||||
@ -114,6 +118,9 @@ genLoginSignupForm auth =
|
||||
-- Google
|
||||
"isGoogleAuthEnabled" .= AS.Auth.isGoogleAuthEnabled auth,
|
||||
"googleSignInPath" .= OAuth.serverLoginUrl googleAuthProvider,
|
||||
-- Keycloak
|
||||
"isKeycloakAuthEnabled" .= AS.Auth.isKeycloakAuthEnabled auth,
|
||||
"keycloakSignInPath" .= OAuth.serverLoginUrl keycloakAuthProvider,
|
||||
-- GitHub
|
||||
"isGitHubAuthEnabled" .= AS.Auth.isGitHubAuthEnabled auth,
|
||||
"gitHubSignInPath" .= OAuth.serverLoginUrl gitHubAuthProvider,
|
||||
|
@ -7,7 +7,11 @@ import Data.Aeson (object, (.=))
|
||||
import StrongPath (File', Path', Rel', reldir, relfile)
|
||||
import qualified StrongPath as SP
|
||||
import qualified Wasp.AppSpec.App.Auth as AS.Auth
|
||||
import Wasp.Generator.AuthProviders (gitHubAuthProvider, googleAuthProvider)
|
||||
import Wasp.Generator.AuthProviders
|
||||
( gitHubAuthProvider,
|
||||
googleAuthProvider,
|
||||
keycloakAuthProvider,
|
||||
)
|
||||
import Wasp.Generator.AuthProviders.OAuth (OAuthAuthProvider)
|
||||
import qualified Wasp.Generator.AuthProviders.OAuth as OAuth
|
||||
import Wasp.Generator.FileDraft (FileDraft)
|
||||
@ -25,11 +29,13 @@ genHelpers auth =
|
||||
return $
|
||||
concat
|
||||
[ [gitHubHelpers | AS.Auth.isGitHubAuthEnabled auth],
|
||||
[googleHelpers | AS.Auth.isGoogleAuthEnabled auth]
|
||||
[googleHelpers | AS.Auth.isGoogleAuthEnabled auth],
|
||||
[keycloakHelpers | AS.Auth.isKeycloakAuthEnabled auth]
|
||||
]
|
||||
where
|
||||
gitHubHelpers = mkHelpersFd gitHubAuthProvider [relfile|GitHub.tsx|]
|
||||
googleHelpers = mkHelpersFd googleAuthProvider [relfile|Google.tsx|]
|
||||
keycloakHelpers = mkHelpersFd keycloakAuthProvider [relfile|Keycloak.tsx|]
|
||||
|
||||
mkHelpersFd :: OAuthAuthProvider -> Path' Rel' File' -> FileDraft
|
||||
mkHelpersFd provider helpersFp =
|
||||
|
@ -28,6 +28,7 @@ genNewClientAuth spec =
|
||||
<++> genAuthEmail auth
|
||||
<++> genAuthUsername auth
|
||||
<++> genAuthGoogle auth
|
||||
<++> genAuthKeycloak auth
|
||||
<++> genAuthGitHub auth
|
||||
where
|
||||
maybeAuth = AS.App.auth $ snd $ getApp spec
|
||||
@ -68,6 +69,12 @@ genAuthGoogle auth =
|
||||
then sequence [genFileCopy [relfile|client/auth/google.ts|]]
|
||||
else return []
|
||||
|
||||
genAuthKeycloak :: AS.Auth.Auth -> Generator [FileDraft]
|
||||
genAuthKeycloak auth =
|
||||
if AS.Auth.isKeycloakAuthEnabled auth
|
||||
then sequence [genFileCopy [relfile|client/auth/keycloak.ts|]]
|
||||
else return []
|
||||
|
||||
genAuthGitHub :: AS.Auth.Auth -> Generator [FileDraft]
|
||||
genAuthGitHub auth =
|
||||
if AS.Auth.isGitHubAuthEnabled auth
|
||||
|
@ -26,7 +26,11 @@ import qualified Wasp.AppSpec.App.Auth as AS.App.Auth
|
||||
import qualified Wasp.AppSpec.App.Auth as AS.Auth
|
||||
import qualified Wasp.AppSpec.App.Dependency as App.Dependency
|
||||
import Wasp.AppSpec.Valid (getApp)
|
||||
import Wasp.Generator.AuthProviders (gitHubAuthProvider, googleAuthProvider)
|
||||
import Wasp.Generator.AuthProviders
|
||||
( gitHubAuthProvider,
|
||||
googleAuthProvider,
|
||||
keycloakAuthProvider,
|
||||
)
|
||||
import Wasp.Generator.AuthProviders.OAuth
|
||||
( OAuthAuthProvider,
|
||||
clientOAuthCallbackPath,
|
||||
@ -49,6 +53,7 @@ genOAuthAuth auth
|
||||
| AS.Auth.isExternalAuthEnabled auth =
|
||||
genOAuthHelpers auth
|
||||
<++> genOAuthProvider googleAuthProvider (AS.Auth.google . AS.Auth.methods $ auth)
|
||||
<++> genOAuthProvider keycloakAuthProvider (AS.Auth.keycloak . AS.Auth.methods $ auth)
|
||||
<++> genOAuthProvider gitHubAuthProvider (AS.Auth.gitHub . AS.Auth.methods $ auth)
|
||||
| otherwise = return []
|
||||
|
||||
|
@ -20,7 +20,13 @@ import qualified Wasp.AppSpec.App as AS.App
|
||||
import qualified Wasp.AppSpec.App.Auth as AS.Auth
|
||||
import qualified Wasp.AppSpec.App.Dependency as AS.Dependency
|
||||
import Wasp.AppSpec.Valid (getApp)
|
||||
import Wasp.Generator.AuthProviders (emailAuthProvider, gitHubAuthProvider, googleAuthProvider, localAuthProvider)
|
||||
import Wasp.Generator.AuthProviders
|
||||
( emailAuthProvider,
|
||||
gitHubAuthProvider,
|
||||
googleAuthProvider,
|
||||
keycloakAuthProvider,
|
||||
localAuthProvider,
|
||||
)
|
||||
import qualified Wasp.Generator.AuthProviders.Email as EmailProvider
|
||||
import qualified Wasp.Generator.AuthProviders.Local as LocalProvider
|
||||
import qualified Wasp.Generator.AuthProviders.OAuth as OAuthProvider
|
||||
@ -72,6 +78,7 @@ genProvidersIndex auth = return $ C.mkTmplFdWithData [relfile|src/auth/providers
|
||||
<$> concat
|
||||
[ [OAuthProvider.providerId gitHubAuthProvider | AS.Auth.isGitHubAuthEnabled auth],
|
||||
[OAuthProvider.providerId googleAuthProvider | AS.Auth.isGoogleAuthEnabled auth],
|
||||
[OAuthProvider.providerId keycloakAuthProvider | AS.Auth.isKeycloakAuthEnabled auth],
|
||||
[LocalProvider.providerId localAuthProvider | AS.Auth.isUsernameAndPasswordAuthEnabled auth],
|
||||
[EmailProvider.providerId emailAuthProvider | AS.Auth.isEmailAuthEnabled auth]
|
||||
]
|
||||
|
@ -9,7 +9,6 @@ import Data.List (intercalate)
|
||||
import Data.Maybe (fromJust)
|
||||
import qualified StrongPath as SP
|
||||
import Test.Tasty.Hspec
|
||||
import qualified Wasp.AI.GenerateNewProject.Common as Auth
|
||||
import Wasp.Analyzer
|
||||
import Wasp.Analyzer.Parser (Ctx)
|
||||
import qualified Wasp.Analyzer.TypeChecker as TC
|
||||
@ -145,6 +144,7 @@ spec_Analyzer = do
|
||||
{ Auth.userSignupFields = Just $ ExtImport (ExtImportField "getUserFields") (fromJust $ SP.parseRelFileP "auth/signup.js")
|
||||
},
|
||||
Auth.google = Nothing,
|
||||
Auth.keycloak = Nothing,
|
||||
Auth.gitHub = Nothing,
|
||||
Auth.email = Nothing
|
||||
},
|
||||
|
@ -104,6 +104,7 @@ spec_AppSpecValid = do
|
||||
{ AS.Auth.usernameAndPassword = Just AS.Auth.UsernameAndPasswordConfig {AS.Auth.userSignupFields = Nothing},
|
||||
AS.Auth.google = Nothing,
|
||||
AS.Auth.gitHub = Nothing,
|
||||
AS.Auth.keycloak = Nothing,
|
||||
AS.Auth.email = Nothing
|
||||
},
|
||||
AS.Auth.onAuthFailedRedirectTo = "/",
|
||||
@ -185,7 +186,7 @@ spec_AppSpecValid = do
|
||||
}
|
||||
|
||||
it "returns no error if app.auth is not set" $ do
|
||||
ASV.validateAppSpec (makeSpec (AS.Auth.AuthMethods {usernameAndPassword = Nothing, google = Nothing, gitHub = Nothing, email = Nothing}) validUserEntity) `shouldBe` []
|
||||
ASV.validateAppSpec (makeSpec (AS.Auth.AuthMethods {usernameAndPassword = Nothing, google = Nothing, keycloak = Nothing, gitHub = Nothing, email = Nothing}) validUserEntity) `shouldBe` []
|
||||
|
||||
it "returns no error if app.auth is set and only one of UsernameAndPassword and Email is used" $ do
|
||||
ASV.validateAppSpec
|
||||
@ -197,6 +198,7 @@ spec_AppSpecValid = do
|
||||
{ AS.Auth.userSignupFields = Nothing
|
||||
},
|
||||
google = Nothing,
|
||||
keycloak = Nothing,
|
||||
gitHub = Nothing,
|
||||
email = Nothing
|
||||
}
|
||||
@ -204,7 +206,7 @@ spec_AppSpecValid = do
|
||||
validUserEntity
|
||||
)
|
||||
`shouldBe` []
|
||||
ASV.validateAppSpec (makeSpec (AS.Auth.AuthMethods {usernameAndPassword = Nothing, google = Nothing, gitHub = Nothing, email = Just emailAuthConfig}) validUserEntity) `shouldBe` []
|
||||
ASV.validateAppSpec (makeSpec (AS.Auth.AuthMethods {usernameAndPassword = Nothing, google = Nothing, keycloak = Nothing, gitHub = Nothing, email = Just emailAuthConfig}) validUserEntity) `shouldBe` []
|
||||
|
||||
it "returns an error if app.auth is set and both UsernameAndPassword and Email are used" $ do
|
||||
ASV.validateAppSpec
|
||||
@ -216,6 +218,7 @@ spec_AppSpecValid = do
|
||||
{ AS.Auth.userSignupFields = Nothing
|
||||
},
|
||||
google = Nothing,
|
||||
keycloak = Nothing,
|
||||
gitHub = Nothing,
|
||||
email = Just emailAuthConfig
|
||||
}
|
||||
@ -281,7 +284,7 @@ spec_AppSpecValid = do
|
||||
Just
|
||||
AS.Auth.Auth
|
||||
{ AS.Auth.methods =
|
||||
AS.Auth.AuthMethods {email = Just emailAuthConfig, usernameAndPassword = Nothing, google = Nothing, gitHub = Nothing},
|
||||
AS.Auth.AuthMethods {email = Just emailAuthConfig, usernameAndPassword = Nothing, google = Nothing, keycloak = Nothing, gitHub = Nothing},
|
||||
AS.Auth.userEntity = AS.Core.Ref.Ref userEntityName,
|
||||
AS.Auth.externalAuthEntity = Nothing,
|
||||
AS.Auth.onAuthFailedRedirectTo = "/",
|
||||
|
@ -3,6 +3,7 @@
|
||||
--auth-pills-email: #e0f2fe;
|
||||
--auth-pills-github: #f1f5f9;
|
||||
--auth-pills-google: #ecfccb;
|
||||
--auth-pills-keycloak: #d0ebf5;
|
||||
--auth-pills-username-and-pass: #fce7f3;
|
||||
}
|
||||
|
||||
@ -11,5 +12,6 @@
|
||||
--auth-pills-email: #0c4a6e;
|
||||
--auth-pills-github: #334155;
|
||||
--auth-pills-google: #365314;
|
||||
--auth-pills-keycloak: #2d5866;
|
||||
--auth-pills-username-and-pass: #831843;
|
||||
}
|
||||
|
@ -20,14 +20,6 @@ export function Pill({ children, linkToPage, style = {} }) {
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
:root {
|
||||
--auth-pills-email: #e0f2fe;
|
||||
--auth-pills-github: #f1f5f9;
|
||||
--auth-pills-google: #ecfccb;
|
||||
--auth-pills-username-and-pass: #fce7f3;
|
||||
}
|
||||
*/
|
||||
export function EmailPill() {
|
||||
return (
|
||||
<Pill
|
||||
@ -79,3 +71,16 @@ export function GooglePill() {
|
||||
</Pill>
|
||||
)
|
||||
}
|
||||
|
||||
export function KeycloakPill() {
|
||||
return (
|
||||
<Pill
|
||||
style={{
|
||||
backgroundColor: 'var(--auth-pills-keycloak)',
|
||||
}}
|
||||
linkToPage="/docs/auth/social-auth/keycloak"
|
||||
>
|
||||
Keycloak
|
||||
</Pill>
|
||||
)
|
||||
}
|
||||
|
@ -16,6 +16,11 @@ export function SocialAuthGrid({
|
||||
description: 'Users sign in with their Github account.',
|
||||
linkToDocs: '/docs/auth/social-auth/github' + pagePart,
|
||||
},
|
||||
{
|
||||
title: 'Keycloak',
|
||||
description: 'Users sign in with their Keycloak account.',
|
||||
linkToDocs: '/docs/auth/social-auth/keycloak' + pagePart,
|
||||
},
|
||||
]
|
||||
return (
|
||||
<>
|
||||
|
547
web/docs/auth/social-auth/keycloak.md
Normal file
547
web/docs/auth/social-auth/keycloak.md
Normal file
@ -0,0 +1,547 @@
|
||||
---
|
||||
title: Keycloak
|
||||
---
|
||||
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
import DefaultBehaviour from './\_default-behaviour.md';
|
||||
import OverrideIntro from './\_override-intro.md';
|
||||
import OverrideExampleIntro from './\_override-example-intro.md';
|
||||
import UsingAuthNote from './\_using-auth-note.md';
|
||||
import WaspFileStructureNote from './\_wasp-file-structure-note.md';
|
||||
import GetUserFieldsType from './\_getuserfields-type.md';
|
||||
import ApiReferenceIntro from './\_api-reference-intro.md';
|
||||
import UserSignupFieldsExplainer from '../\_user-signup-fields-explainer.md';
|
||||
|
||||
Wasp supports Keycloak Authentication out of the box.
|
||||
|
||||
[Keycloak](https://www.keycloak.org/) is an open-source identity and access management solution for modern applications and services. Keycloak provides both SAML and OpenID protocol solutions. It also has a very flexible and powerful administration UI.
|
||||
|
||||
Let's walk through enabling Keycloak authentication, explain some of the default settings, and show how to override them.
|
||||
|
||||
## Setting up Keycloak Auth
|
||||
|
||||
Enabling Keycloak Authentication comes down to a series of steps:
|
||||
|
||||
1. Enabling Keycloak authentication in the Wasp file.
|
||||
1. Adding the `User` entity.
|
||||
1. Creating a Keycloak client.
|
||||
1. Adding the necessary Routes and Pages
|
||||
1. Using Auth UI components in our Pages.
|
||||
|
||||
<WaspFileStructureNote />
|
||||
|
||||
### 1. Adding Keycloak Auth to Your Wasp File
|
||||
|
||||
Let's start by properly configuring the Auth object:
|
||||
|
||||
<Tabs groupId="js-ts">
|
||||
<TabItem value="js" label="JavaScript">
|
||||
|
||||
```wasp title="main.wasp"
|
||||
app myApp {
|
||||
wasp: {
|
||||
version: "^0.13.0"
|
||||
},
|
||||
title: "My App",
|
||||
auth: {
|
||||
// 1. Specify the User entity (we'll define it next)
|
||||
// highlight-next-line
|
||||
userEntity: User,
|
||||
methods: {
|
||||
// 2. Enable Keycloak Auth
|
||||
// highlight-next-line
|
||||
keycloak: {}
|
||||
},
|
||||
onAuthFailedRedirectTo: "/login"
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="ts" label="TypeScript">
|
||||
|
||||
```wasp title="main.wasp"
|
||||
app myApp {
|
||||
wasp: {
|
||||
version: "^0.13.0"
|
||||
},
|
||||
title: "My App",
|
||||
auth: {
|
||||
// 1. Specify the User entity (we'll define it next)
|
||||
// highlight-next-line
|
||||
userEntity: User,
|
||||
methods: {
|
||||
// 2. Enable Keycloak Auth
|
||||
// highlight-next-line
|
||||
keycloak: {}
|
||||
},
|
||||
onAuthFailedRedirectTo: "/login"
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
The `userEntity` is explained in [the social auth overview](../../auth/social-auth/overview#social-login-entity).
|
||||
|
||||
### 2. Adding the User Entity
|
||||
|
||||
Let's now define the `app.auth.userEntity` entity:
|
||||
|
||||
<Tabs groupId="js-ts">
|
||||
<TabItem value="js" label="JavaScript">
|
||||
|
||||
```wasp title="main.wasp"
|
||||
// ...
|
||||
// 3. Define the User entity
|
||||
// highlight-next-line
|
||||
entity User {=psl
|
||||
id Int @id @default(autoincrement())
|
||||
// ...
|
||||
psl=}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="ts" label="TypeScript">
|
||||
|
||||
```wasp title="main.wasp"
|
||||
// ...
|
||||
// 3. Define the User entity
|
||||
// highlight-next-line
|
||||
entity User {=psl
|
||||
id Int @id @default(autoincrement())
|
||||
// ...
|
||||
psl=}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### 3. Creating a Keycloak Client
|
||||
|
||||
1. Log into your Keycloak admin console.
|
||||
1. Under **Clients**, click on **Create Client**.
|
||||
|
||||
![Keycloak Screenshot 1](/img/auth/keycloak/1-keycloak.png)
|
||||
|
||||
1. Fill in the **Client ID** and choose a name for the client.
|
||||
|
||||
![Keycloak Screenshot 2](/img/auth/keycloak/2-keycloak.png)
|
||||
|
||||
1. In the next step, enable **Client Authentication**.
|
||||
|
||||
![Keycloak Screenshot 3](/img/auth/keycloak/3-keycloak.png)
|
||||
|
||||
1. Under **Valid Redirect URIs**, add `http://localhost:3001/auth/keycloak/callback` for local development.
|
||||
|
||||
![Keycloak Screenshot 4](/img/auth/keycloak/4-keycloak.png)
|
||||
|
||||
- Once you know on which URL(s) your API server will be deployed, also add those URL(s).
|
||||
- For example: `https://my-server-url.com/auth/keycloak/callback`.
|
||||
|
||||
1. Click **Save**.
|
||||
1. In the **Credentials** tab, copy the **Client Secret** value, which we'll use in the next step.
|
||||
|
||||
![Keycloak Screenshot 5](/img/auth/keycloak/5-keycloak.png)
|
||||
|
||||
### 4. Adding Environment Variables
|
||||
|
||||
Add these environment variables to the `.env.server` file at the root of your project (take their values from the previous step):
|
||||
|
||||
```bash title=".env.server"
|
||||
KEYCLOAK_CLIENT_ID=your-keycloak-client-id
|
||||
KEYCLOAK_CLIENT_SECRET=your-keycloak-client-secret
|
||||
KEYCLOAK_REALM_URL=https://your-keycloak-url.com/realms/master
|
||||
```
|
||||
|
||||
We assumed in the `KEYCLOAK_REALM_URL` env variable that you are using the `master` realm. If you are using a different realm, replace `master` with your realm name.
|
||||
|
||||
### 5. Adding the Necessary Routes and Pages
|
||||
|
||||
Let's define the necessary authentication Routes and Pages.
|
||||
|
||||
Add the following code to your `main.wasp` file:
|
||||
|
||||
<Tabs groupId="js-ts">
|
||||
<TabItem value="js" label="JavaScript">
|
||||
|
||||
```wasp title="main.wasp"
|
||||
// ...
|
||||
|
||||
// 6. Define the routes
|
||||
route LoginRoute { path: "/login", to: LoginPage }
|
||||
page LoginPage {
|
||||
component: import { Login } from "@src/pages/auth.jsx"
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="ts" label="TypeScript">
|
||||
|
||||
```wasp title="main.wasp"
|
||||
// ...
|
||||
|
||||
// 6. Define the routes
|
||||
route LoginRoute { path: "/login", to: LoginPage }
|
||||
page LoginPage {
|
||||
component: import { Login } from "@src/pages/auth.tsx"
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
We'll define the React components for these pages in the `src/pages/auth.{jsx,tsx}` file below.
|
||||
|
||||
### 6. Create the Client Pages
|
||||
|
||||
:::info
|
||||
We are using [Tailwind CSS](https://tailwindcss.com/) to style the pages. Read more about how to add it [here](../../project/css-frameworks).
|
||||
:::
|
||||
|
||||
Let's now create an `auth.{jsx,tsx}` file in the `src/pages`.
|
||||
It should have the following code:
|
||||
|
||||
<Tabs groupId="js-ts">
|
||||
<TabItem value="js" label="JavaScript">
|
||||
|
||||
```tsx title="src/pages/auth.jsx"
|
||||
import { LoginForm } from 'wasp/client/auth'
|
||||
|
||||
export function Login() {
|
||||
return (
|
||||
<Layout>
|
||||
<LoginForm />
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
||||
// A layout component to center the content
|
||||
export function Layout({ children }) {
|
||||
return (
|
||||
<div className="w-full h-full bg-white">
|
||||
<div className="min-w-full min-h-[75vh] flex items-center justify-center">
|
||||
<div className="w-full h-full max-w-sm p-5 bg-white">
|
||||
<div>{children}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="ts" label="TypeScript">
|
||||
|
||||
```tsx title="src/pages/auth.tsx"
|
||||
import { LoginForm } from 'wasp/client/auth'
|
||||
|
||||
export function Login() {
|
||||
return (
|
||||
<Layout>
|
||||
<LoginForm />
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
||||
// A layout component to center the content
|
||||
export function Layout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<div className="w-full h-full bg-white">
|
||||
<div className="min-w-full min-h-[75vh] flex items-center justify-center">
|
||||
<div className="w-full h-full max-w-sm p-5 bg-white">
|
||||
<div>{children}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
:::info Auth UI
|
||||
Our pages use an automatically generated Auth UI component. Read more about Auth UI components [here](../../auth/ui).
|
||||
:::
|
||||
|
||||
### Conclusion
|
||||
|
||||
Yay, we've successfully set up Keycloak Auth!
|
||||
|
||||
Running `wasp db migrate-dev` and `wasp start` should now give you a working app with authentication.
|
||||
To see how to protect specific pages (i.e., hide them from non-authenticated users), read the docs on [using auth](../../auth/overview).
|
||||
|
||||
## Default Behaviour
|
||||
|
||||
Add `keycloak: {}` to the `auth.methods` dictionary to use it with default settings:
|
||||
|
||||
<Tabs groupId="js-ts">
|
||||
<TabItem value="js" label="JavaScript">
|
||||
|
||||
```wasp title=main.wasp
|
||||
app myApp {
|
||||
wasp: {
|
||||
version: "^0.13.0"
|
||||
},
|
||||
title: "My App",
|
||||
auth: {
|
||||
userEntity: User,
|
||||
methods: {
|
||||
// highlight-next-line
|
||||
keycloak: {}
|
||||
},
|
||||
onAuthFailedRedirectTo: "/login"
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="ts" label="TypeScript">
|
||||
|
||||
```wasp title=main.wasp
|
||||
app myApp {
|
||||
wasp: {
|
||||
version: "^0.13.0"
|
||||
},
|
||||
title: "My App",
|
||||
auth: {
|
||||
userEntity: User,
|
||||
methods: {
|
||||
// highlight-next-line
|
||||
keycloak: {}
|
||||
},
|
||||
onAuthFailedRedirectTo: "/login"
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
<DefaultBehaviour />
|
||||
|
||||
## Overrides
|
||||
|
||||
<OverrideIntro />
|
||||
|
||||
### Data Received From Keycloak
|
||||
|
||||
We are using Keycloak's API and its `/userinfo` endpoint to fetch the user's data.
|
||||
|
||||
```ts title="Keycloak user data"
|
||||
{
|
||||
sub: '5adba8fc-3ea6-445a-a379-13f0bb0b6969',
|
||||
email_verified: true,
|
||||
name: 'Test User',
|
||||
preferred_username: 'test',
|
||||
given_name: 'Test',
|
||||
family_name: 'User',
|
||||
email: 'test@example.com'
|
||||
}
|
||||
```
|
||||
|
||||
The fields you receive will depend on the scopes you requested. The default scope is set to `profile` only. If you want to get the user's email, you need to specify the `email` scope in the `configFn` function.
|
||||
|
||||
<small>
|
||||
|
||||
For up-to-date info about the data received from Keycloak, please refer to the [Keycloak API documentation](https://www.keycloak.org/docs-api/23.0.7/javadocs/org/keycloak/representations/UserInfo.html).
|
||||
</small>
|
||||
|
||||
### Using the Data Received From Keycloak
|
||||
|
||||
<OverrideExampleIntro />
|
||||
|
||||
<Tabs groupId="js-ts">
|
||||
<TabItem value="js" label="JavaScript">
|
||||
|
||||
```wasp title="main.wasp"
|
||||
app myApp {
|
||||
wasp: {
|
||||
version: "^0.13.0"
|
||||
},
|
||||
title: "My App",
|
||||
auth: {
|
||||
userEntity: User,
|
||||
methods: {
|
||||
keycloak: {
|
||||
// highlight-next-line
|
||||
configFn: import { getConfig } from "@src/auth/keycloak.js",
|
||||
// highlight-next-line
|
||||
userSignupFields: import { userSignupFields } from "@src/auth/keycloak.js"
|
||||
}
|
||||
},
|
||||
onAuthFailedRedirectTo: "/login"
|
||||
},
|
||||
}
|
||||
|
||||
entity User {=psl
|
||||
id Int @id @default(autoincrement())
|
||||
username String @unique
|
||||
displayName String
|
||||
psl=}
|
||||
|
||||
// ...
|
||||
```
|
||||
|
||||
```js title=src/auth/keycloak.js
|
||||
export const userSignupFields = {
|
||||
username: () => "hardcoded-username",
|
||||
displayName: (data) => data.profile.name,
|
||||
}
|
||||
|
||||
export function getConfig() {
|
||||
return {
|
||||
scopes: ['profile', 'email'],
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="ts" label="TypeScript">
|
||||
|
||||
```wasp title="main.wasp"
|
||||
app myApp {
|
||||
wasp: {
|
||||
version: "^0.13.0"
|
||||
},
|
||||
title: "My App",
|
||||
auth: {
|
||||
userEntity: User,
|
||||
methods: {
|
||||
keycloak: {
|
||||
// highlight-next-line
|
||||
configFn: import { getConfig } from "@src/auth/keycloak.js",
|
||||
// highlight-next-line
|
||||
userSignupFields: import { userSignupFields } from "@src/auth/keycloak.js"
|
||||
}
|
||||
},
|
||||
onAuthFailedRedirectTo: "/login"
|
||||
},
|
||||
}
|
||||
|
||||
entity User {=psl
|
||||
id Int @id @default(autoincrement())
|
||||
username String @unique
|
||||
displayName String
|
||||
psl=}
|
||||
|
||||
// ...
|
||||
```
|
||||
|
||||
```ts title=src/auth/keycloak.ts
|
||||
import { defineUserSignupFields } from 'wasp/server/auth'
|
||||
|
||||
export const userSignupFields = defineUserSignupFields({
|
||||
username: () => "hardcoded-username",
|
||||
displayName: (data: any) => data.profile.name,
|
||||
})
|
||||
|
||||
export function getConfig() {
|
||||
return {
|
||||
scopes: ['profile', 'email'],
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<GetUserFieldsType />
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Using Auth
|
||||
|
||||
<UsingAuthNote />
|
||||
|
||||
## API Reference
|
||||
|
||||
<ApiReferenceIntro />
|
||||
|
||||
<Tabs groupId="js-ts">
|
||||
<TabItem value="js" label="JavaScript">
|
||||
|
||||
```wasp title="main.wasp"
|
||||
app myApp {
|
||||
wasp: {
|
||||
version: "^0.13.0"
|
||||
},
|
||||
title: "My App",
|
||||
auth: {
|
||||
userEntity: User,
|
||||
methods: {
|
||||
keycloak: {
|
||||
// highlight-next-line
|
||||
configFn: import { getConfig } from "@src/auth/keycloak.js",
|
||||
// highlight-next-line
|
||||
userSignupFields: import { userSignupFields } from "@src/auth/keycloak.js"
|
||||
}
|
||||
},
|
||||
onAuthFailedRedirectTo: "/login"
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="ts" label="TypeScript">
|
||||
|
||||
```wasp title="main.wasp"
|
||||
app myApp {
|
||||
wasp: {
|
||||
version: "^0.13.0"
|
||||
},
|
||||
title: "My App",
|
||||
auth: {
|
||||
userEntity: User,
|
||||
methods: {
|
||||
keycloak: {
|
||||
// highlight-next-line
|
||||
configFn: import { getConfig } from "@src/auth/keycloak.js",
|
||||
// highlight-next-line
|
||||
userSignupFields: import { userSignupFields } from "@src/auth/keycloak.js"
|
||||
}
|
||||
},
|
||||
onAuthFailedRedirectTo: "/login"
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
The `keycloak` dict has the following properties:
|
||||
|
||||
- #### `configFn: ExtImport`
|
||||
|
||||
This function must return an object with the scopes for the OAuth provider.
|
||||
|
||||
<Tabs groupId="js-ts">
|
||||
<TabItem value="js" label="JavaScript">
|
||||
|
||||
```js title=src/auth/keycloak.js
|
||||
export function getConfig() {
|
||||
return {
|
||||
scopes: ['profile', 'email'],
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="ts" label="TypeScript">
|
||||
|
||||
```ts title=src/auth/keycloak.ts
|
||||
export function getConfig() {
|
||||
return {
|
||||
scopes: ['profile', 'email'],
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
- #### `userSignupFields: ExtImport`
|
||||
|
||||
<UserSignupFieldsExplainer />
|
||||
|
||||
Read more about the `userSignupFields` function [here](../overview#1-defining-extra-fields).
|
@ -2,7 +2,7 @@
|
||||
title: Auth UI
|
||||
---
|
||||
|
||||
import { EmailPill, UsernameAndPasswordPill, GithubPill, GooglePill } from "./Pills";
|
||||
import { EmailPill, UsernameAndPasswordPill, GithubPill, GooglePill, KeycloakPill } from "./Pills";
|
||||
|
||||
To make using authentication in your app as easy as possible, Wasp generates the server-side code but also the client-side UI for you. It enables you to quickly get the login, signup, password reset and email verification flows in your app.
|
||||
|
||||
@ -110,7 +110,7 @@ The following components are available for you to use in your app:
|
||||
|
||||
### Login Form
|
||||
|
||||
Used with <UsernameAndPasswordPill />, <EmailPill />, <GithubPill /> and <GooglePill /> authentication.
|
||||
Used with <UsernameAndPasswordPill />, <EmailPill />, <GithubPill />, <GooglePill /> and <KeycloakPill /> authentication.
|
||||
|
||||
![Login form](/img/authui/login.png)
|
||||
|
||||
@ -165,7 +165,7 @@ It will automatically show the correct authentication providers based on your `m
|
||||
|
||||
### Signup Form
|
||||
|
||||
Used with <UsernameAndPasswordPill />, <EmailPill />, <GithubPill /> and <GooglePill /> authentication.
|
||||
Used with <UsernameAndPasswordPill />, <EmailPill />, <GithubPill />, <GooglePill /> and <KeycloakPill /> authentication.
|
||||
|
||||
![Signup form](/img/authui/signup.png)
|
||||
|
||||
|
@ -65,6 +65,7 @@ module.exports = {
|
||||
'auth/social-auth/overview',
|
||||
'auth/social-auth/github',
|
||||
'auth/social-auth/google',
|
||||
'auth/social-auth/keycloak',
|
||||
],
|
||||
},
|
||||
'auth/entities/entities',
|
||||
|
@ -23,6 +23,11 @@ export function AuthMethodsGrid() {
|
||||
description: 'Users sign in with their Github account',
|
||||
linkToDocs: '/docs/auth/social-auth/github',
|
||||
},
|
||||
{
|
||||
title: 'Keycloak',
|
||||
description: 'Users sign in with their Keycloak account',
|
||||
linkToDocs: '/docs/auth/social-auth/keycloak',
|
||||
}
|
||||
]
|
||||
return (
|
||||
<>
|
||||
|
BIN
web/static/img/auth/keycloak/1-keycloak.png
Normal file
BIN
web/static/img/auth/keycloak/1-keycloak.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 56 KiB |
BIN
web/static/img/auth/keycloak/2-keycloak.png
Normal file
BIN
web/static/img/auth/keycloak/2-keycloak.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 35 KiB |
BIN
web/static/img/auth/keycloak/3-keycloak.png
Normal file
BIN
web/static/img/auth/keycloak/3-keycloak.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 41 KiB |
BIN
web/static/img/auth/keycloak/4-keycloak.png
Normal file
BIN
web/static/img/auth/keycloak/4-keycloak.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 42 KiB |
BIN
web/static/img/auth/keycloak/5-keycloak.png
Normal file
BIN
web/static/img/auth/keycloak/5-keycloak.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 36 KiB |
Loading…
Reference in New Issue
Block a user