2
0

(auth) Add custom OAuth provider support

Closes #42
This commit is contained in:
Baptiste Arnaud
2023-01-02 08:29:46 +01:00
parent 60ed0b2d4a
commit b9d38935a6
4 changed files with 67 additions and 1 deletions

View File

@ -105,6 +105,15 @@ export const SocialLoginButtons = ({ providers }: Props) => {
Continue with {providers['azure-ad'].name} Continue with {providers['azure-ad'].name}
</Button> </Button>
)} )}
{providers?.['custom-oauth'] && (
<Button
onClick={handleAzureAdClick}
isLoading={['loading', 'authenticated'].includes(status)}
variant="outline"
>
Continue with {providers['custom-oauth'].name}
</Button>
)}
</Stack> </Stack>
) )
} }

View File

@ -10,7 +10,7 @@ import { Provider } from 'next-auth/providers'
import { NextApiRequest, NextApiResponse } from 'next' import { NextApiRequest, NextApiResponse } from 'next'
import { CustomAdapter } from './adapter' import { CustomAdapter } from './adapter'
import { User } from 'db' import { User } from 'db'
import { env, isNotEmpty } from 'utils' import { env, getAtPath, isNotEmpty } from 'utils'
import { mockedUser } from '@/features/auth' import { mockedUser } from '@/features/auth'
const providers: Provider[] = [] const providers: Provider[] = []
@ -97,6 +97,34 @@ if (
) )
} }
if (isNotEmpty(process.env.CUSTOM_OAUTH_AUTHORIZATION_URL)) {
providers.push({
id: 'custom-oauth',
name: process.env.CUSTOM_OAUTH_NAME ?? 'Custom OAuth',
type: 'oauth',
authorization: process.env.CUSTOM_OAUTH_AUTHORIZATION_URL,
token: process.env.CUSTOM_OAUTH_TOKEN_URL,
userinfo: process.env.CUSTOM_OAUTH_USERINFO_URL,
profile(profile) {
return {
id: getAtPath(profile, process.env.CUSTOM_OAUTH_USER_ID_PATH ?? 'id'),
name: getAtPath(
profile,
process.env.CUSTOM_OAUTH_USER_NAME_PATH ?? 'name'
),
email: getAtPath(
profile,
process.env.CUSTOM_OAUTH_USER_EMAIL_PATH ?? 'email'
),
image: getAtPath(
profile,
process.env.CUSTOM_OAUTH_USER_IMAGE_PATH ?? 'image'
),
} as User
},
})
}
const handler = (req: NextApiRequest, res: NextApiResponse) => { const handler = (req: NextApiRequest, res: NextApiResponse) => {
if ( if (
req.method === 'GET' && req.method === 'GET' &&

View File

@ -103,6 +103,21 @@ The Authorization callback URL should be `$NEXTAUTH_URL/api/auth/callback/azure-
| AZURE_AD_CLIENT_SECRET | -- | Application client secret. Can be obtained from Azure Portal. | | AZURE_AD_CLIENT_SECRET | -- | Application client secret. Can be obtained from Azure Portal. |
| AZURE_AD_TENANT_ID | -- | Azure Tenant ID | | AZURE_AD_TENANT_ID | -- | Azure Tenant ID |
## Custom OAuth Provider (Auth)
| Parameter | Default | Description |
| ------------------------------ | ------------ | ----------------------------------------------------------------------- |
| CUSTOM_OAUTH_NAME | Custom OAuth | Provider name. Is displayed in the sign in form. |
| CUSTOM_OAUTH_AUTHORIZATION_URL | -- | OAuth autorization URL (i.e. `https://kauth.kakao.com/oauth/authorize`) |
| CUSTOM_OAUTH_TOKEN_URL | -- | OAuth token URL (i.e. `https://kauth.kakao.com/oauth/token`) |
| CUSTOM_OAUTH_USERINFO_URL | -- | User info URL (i.e. `https://kapi.kakao.com/v2/user/me`) |
| CUSTOM_OAUTH_USER_ID_PATH | id | Used to map the id from the user info object |
| CUSTOM_OAUTH_USER_NAME_PATH | name | Used to map the name from the user info object |
| CUSTOM_OAUTH_USER_EMAIL_PATH | email | Used to map the email from the user info object |
| CUSTOM_OAUTH_USER_IMAGE_PATH | image | Used to map the image from the user info object |
For `*_PATH` parameters, you can use dot notation to access nested properties (i.e. `account.name`).
## S3 Storage (Media uploads) ## S3 Storage (Media uploads)
Used for uploading images, videos, etc... It can be any S3 compatible object storage service (Minio, Digital Oceans Space, AWS S3...) Used for uploading images, videos, etc... It can be any S3 compatible object storage service (Minio, Digital Oceans Space, AWS S3...)

View File

@ -303,3 +303,17 @@ export const injectCustomHeadCode = (customHeadCode: string) => {
document.head.append(noScriptElement) document.head.append(noScriptElement)
}) })
} }
export const getAtPath = <T>(obj: T, path: string): unknown => {
if (isNotDefined(obj)) return undefined
const pathParts = path.split('.')
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let current: any = obj
for (const part of pathParts) {
if (current === undefined) {
return undefined
}
current = current[part]
}
return current
}