Skip to content

Commit

Permalink
[core] Add more OAuth providers to SignInPage (#3933)
Browse files Browse the repository at this point in the history
  • Loading branch information
bharatkashyap authored Sep 12, 2024
1 parent ae9bb1c commit 6b7e22e
Show file tree
Hide file tree
Showing 39 changed files with 741 additions and 70 deletions.
2 changes: 2 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
coverage:
ignore:
- '*/icons/*'
status:
project:
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ const providers = [
{ id: 'github', name: 'GitHub' },
{ id: 'google', name: 'Google' },
{ id: 'facebook', name: 'Facebook' },
{ id: 'twitter', name: 'Twitter' },
{ id: 'linkedin', name: 'LinkedIn' },
];

// preview-end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ const providers = [
{ id: 'github', name: 'GitHub' },
{ id: 'google', name: 'Google' },
{ id: 'facebook', name: 'Facebook' },
{ id: 'twitter', name: 'Twitter' },
{ id: 'linkedin', name: 'LinkedIn' },
];
// preview-end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ const providers = [
{ id: 'github', name: 'GitHub' },
{ id: 'google', name: 'Google' },
{ id: 'facebook', name: 'Facebook' },
{ id: 'twitter', name: 'Twitter' },
{ id: 'linkedin', name: 'LinkedIn' },
];

// ...
Expand Down
31 changes: 30 additions & 1 deletion docs/data/toolpad/core/components/sign-in-page/sign-in-page.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,36 @@ The `SignInPage` component is a quick way to generate a ready-to-use authenticat

The `SignInPage` component can be set up with an OAuth provider by passing in a list of providers in the `providers` prop, along with a `signIn` function that accepts the `provider` as a parameter.

{{"demo": "OAuthSignInPage.js", "iframe": true}}
{{"demo": "OAuthSignInPage.js", "iframe": true, "height": 500}}

:::info

The following providers are supported and maintained by default:

- Google
- GitHub
- Facebook
- Microsoft (Entra ID)
- Apple
- Auth0
- AWS Cognito
- GitLab
- Instagram
- LINE
- Okta
- FusionAuth
- Twitter
- TikTok
- LinkedIn
- Slack
- Spotify
- Twitch
- Discord
- Keycloak
- Credentials (username/password)

Find details on how to set up each provider in the [Auth.js documentation](https://authjs.dev/getting-started/authentication/oauth/).
:::

## Credentials

Expand Down
5 changes: 4 additions & 1 deletion docs/pages/toolpad/core/api/sign-in-page.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
{
"props": {
"providers": {
"type": { "name": "arrayOf", "description": "Array<{ id: string, name: string }>" },
"type": {
"name": "arrayOf",
"description": "Array&lt;{ id: 'apple'<br>&#124;&nbsp;'auth0'<br>&#124;&nbsp;'cognito'<br>&#124;&nbsp;'credentials'<br>&#124;&nbsp;'discord'<br>&#124;&nbsp;'facebook'<br>&#124;&nbsp;'fusionauth'<br>&#124;&nbsp;'github'<br>&#124;&nbsp;'gitlab'<br>&#124;&nbsp;'google'<br>&#124;&nbsp;'instagram'<br>&#124;&nbsp;'keycloak'<br>&#124;&nbsp;'line'<br>&#124;&nbsp;'linkedin'<br>&#124;&nbsp;'microsoft-entra-id'<br>&#124;&nbsp;'okta'<br>&#124;&nbsp;'slack'<br>&#124;&nbsp;'spotify'<br>&#124;&nbsp;'tiktok'<br>&#124;&nbsp;'twitch'<br>&#124;&nbsp;'twitter', name: string }&gt;"
},
"default": "[]"
},
"signIn": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const NAVIGATION: Navigation = [
];

const BRANDING = {
title: 'My Toolpad Core App',
title: 'My Toolpad Core Next.js Pages next-auth 4 App',
};

const AUTHENTICATION = {
Expand Down
2 changes: 1 addition & 1 deletion examples/core-auth-nextjs-pages/src/pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const NAVIGATION: Navigation = [
];

const BRANDING = {
title: 'My Toolpad Core App',
title: 'My Toolpad Core Next.js Pages App',
};

const AUTHENTICATION = {
Expand Down
2 changes: 1 addition & 1 deletion examples/core-auth-nextjs/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const NAVIGATION: Navigation = [
];

const BRANDING = {
title: 'My Toolpad Core App',
title: 'My Toolpad Core Next.js App',
};

const AUTHENTICATION = {
Expand Down
1 change: 1 addition & 0 deletions packages/create-toolpad-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"dependencies": {
"@inquirer/prompts": "^5.5.0",
"@toolpad/utils": "workspace:*",
"@toolpad/core": "workspace:*",
"chalk": "5.3.0",
"execa": "9.3.1",
"invariant": "2.2.4",
Expand Down
26 changes: 20 additions & 6 deletions packages/create-toolpad-app/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,13 @@ import { satisfies } from 'semver';
import { readJsonFile } from '@toolpad/utils/fs';
import invariant from 'invariant';
import { bashResolvePath } from '@toolpad/utils/cli';
import type { SupportedAuthProvider } from '@toolpad/core';
import generateProject from './generateProject';
import generateStudioProject from './generateStudioProject';
import writeFiles from './writeFiles';
import { downloadAndExtractExample } from './examples';
import type { PackageJson } from './templates/packageType';
import type {
SupportedRouter,
SupportedAuthProvider,
PackageManager,
GenerateProjectOptions,
} from './types';
import type { SupportedRouter, PackageManager, GenerateProjectOptions } from './types';

/**
* Find package.json of the create-toolpad-app package
Expand Down Expand Up @@ -308,6 +304,24 @@ const run = async () => {
choices: [
{ name: 'Google', value: 'google' },
{ name: 'GitHub', value: 'github' },
{ name: 'GitLab', value: 'gitlab' },
{ name: 'Twitter', value: 'twitter' },
{ name: 'Facebook', value: 'facebook' },
{ name: 'Cognito', value: 'cognito' },
{ name: 'Microsoft Entra ID', value: 'microsoft-entra-id' },
{ name: 'Apple', value: 'apple' },
{ name: 'Instagram', value: 'instagram' },
{ name: 'TikTok', value: 'tiktok' },
{ name: 'LinkedIn', value: 'linkedin' },
{ name: 'Slack', value: 'slack' },
{ name: 'Spotify', value: 'spotify' },
{ name: 'Twitch', value: 'twitch' },
{ name: 'Discord', value: 'discord' },
{ name: 'Line', value: 'line' },
{ name: 'Auth0', value: 'auth0' },
{ name: 'Keycloak', value: 'keycloak' },
{ name: 'Okta', value: 'okta' },
{ name: 'FusionAuth', value: 'fusionauth' },
],
});
}
Expand Down
20 changes: 11 additions & 9 deletions packages/create-toolpad-app/src/templates/auth/auth.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { kebabToConstant, capitalize } from '@toolpad/utils/strings';
import { Template, SupportedAuthProvider } from '../../types';
import type { SupportedAuthProvider } from '@toolpad/core';
import { kebabToConstant, kebabToPascal } from '@toolpad/utils/strings';
import { requiresIssuer, requiresTenantId } from './utils';
import { Template } from '../../types';

const CredentialsProviderTemplate = `Credentials({
credentials: {
Expand All @@ -18,6 +20,12 @@ const CredentialsProviderTemplate = `Credentials({
},
}),`;

const oAuthProviderTemplate = (provider: SupportedAuthProvider) => `${kebabToPascal(provider)}({
clientId: process.env.${kebabToConstant(provider)}_CLIENT_ID,
clientSecret: process.env.${kebabToConstant(provider)}_CLIENT_SECRET,
${requiresIssuer(provider) ? `issuer: process.env.${kebabToConstant(provider)}_ISSUER,\n` : ''}${requiresTenantId(provider) ? `tenantId: process.env.${kebabToConstant(provider)}_TENANT_ID,` : ''}
})`;

const checkEnvironmentVariables = (providers: SupportedAuthProvider[] | undefined) => `
const missingVars: string[] = [];
Expand Down Expand Up @@ -47,20 +55,14 @@ if (missingVars.length > 0) {
}
}`;

const oAuthProviderTemplate = (provider: SupportedAuthProvider) => `
${capitalize(provider)}({
clientId: process.env.${kebabToConstant(provider)}_CLIENT_ID,
clientSecret: process.env.${kebabToConstant(provider)}_CLIENT_SECRET,
}),`;

const auth: Template = (options) => {
const providers = options.authProviders;

return `import NextAuth from 'next-auth';
${providers
?.map(
(provider) =>
`import ${capitalize(provider)} from 'next-auth/providers/${provider.toLowerCase()}';`,
`import ${kebabToPascal(provider)} from 'next-auth/providers/${provider.toLowerCase()}';`,
)
.join('\n')}
import type { Provider } from 'next-auth/providers';
Expand Down
12 changes: 7 additions & 5 deletions packages/create-toolpad-app/src/templates/auth/envLocal.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
import { kebabToConstant } from '@toolpad/utils/strings';
import { requiresIssuer, requiresTenantId } from './utils';
import { Template } from '../../types';

const env: Template = (options) => {
const { authProviders: providers } = options;
const oAuthProviders = providers?.filter((provider) => provider !== 'credentials');
const nonCredentialProviders = providers?.filter((provider) => provider !== 'credentials');
return `
# Generate a secret with \`npx auth secret\`
# and replace the value below with it
AUTH_SECRET=secret
# Add the CLIENT_ID and CLIENT_SECRET from your OAuth provider
# to the .env.local file
${oAuthProviders
# Add secrets for your auth providers to the .env.local file
${nonCredentialProviders
?.map(
(provider) => `
${kebabToConstant(provider)}_CLIENT_ID=
${kebabToConstant(provider)}_CLIENT_SECRET=`,
${kebabToConstant(provider)}_CLIENT_SECRET=
${requiresIssuer(provider) ? `${kebabToConstant(provider)}_ISSUER=\n` : ''}${requiresTenantId(provider) ? `${kebabToConstant(provider)}_TENANT_ID=\n` : ''}`,
)
.join('\n')}
`;
Expand Down
14 changes: 14 additions & 0 deletions packages/create-toolpad-app/src/templates/auth/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { SupportedAuthProvider } from '@toolpad/core';

export function requiresIssuer(provider: SupportedAuthProvider) {
return (
provider === 'cognito' ||
provider === 'fusionauth' ||
provider === 'keycloak' ||
provider === 'okta'
);
}

export function requiresTenantId(provider: SupportedAuthProvider) {
return provider === 'microsoft-entra-id' || provider === 'fusionauth';
}
8 changes: 2 additions & 6 deletions packages/create-toolpad-app/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import { PackageJson } from './templates/packageType';

// https://authjs.dev/reference/core/providers#oauthconfigprofile
type SupportedOAuthProvider = 'facebook' | 'github' | 'google';
import type { SupportedAuthProvider } from '@toolpad/core';

// https://authjs.dev/reference/core/providers#providertype
export type SupportedAuthProvider = SupportedOAuthProvider | 'credentials';
import { PackageJson } from './templates/packageType';

export type SupportedRouter = 'nextjs-app' | 'nextjs-pages';
export type PackageManager = 'npm' | 'pnpm' | 'yarn';
Expand Down
2 changes: 1 addition & 1 deletion packages/toolpad-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"build:types": "tsc -b tsconfig.build.json",
"predev": "pnpm clean",
"dev": "concurrently \"pnpm build:stable --watch\" \"pnpm build:types --watch --preserveWatchOutput\"",
"check-types": "tsc --noEmit",
"check-types": "pnpm build:types && tsc --noEmit",
"test": "vitest run --coverage",
"test:dev": "vitest",
"test:browser": "vitest run --browser.enabled",
Expand Down
Loading

0 comments on commit 6b7e22e

Please sign in to comment.