Merge pull request #32 from laurin-wolf/10-add-gitlab-idp
Add gitlab idp
This commit is contained in:
13
apps/builder/assets/logos/GitlabLogo.tsx
Normal file
13
apps/builder/assets/logos/GitlabLogo.tsx
Normal file
@ -0,0 +1,13 @@
|
||||
import { IconProps, Icon } from '@chakra-ui/react'
|
||||
|
||||
export const GitlabLogo = (props: IconProps) => (
|
||||
<Icon viewBox="0 0 256 236" {...props}>
|
||||
<path d="M128.075 236.075l47.104-144.97H80.97l47.104 144.97z" fill="#E24329" />
|
||||
<path d="M128.075 236.074L80.97 91.104H14.956l113.119 144.97z" fill="#FC6D26" />
|
||||
<path d="M14.956 91.104L.642 135.16a9.752 9.752 0 0 0 3.542 10.903l123.891 90.012-113.12-144.97z" fill="#FCA326" />
|
||||
<path d="M14.956 91.105H80.97L52.601 3.79c-1.46-4.493-7.816-4.492-9.275 0l-28.37 87.315z" fill="#E24329" />
|
||||
<path d="M128.075 236.074l47.104-144.97h66.015l-113.12 144.97z" fill="#FC6D26" />
|
||||
<path d="M241.194 91.104l14.314 44.056a9.752 9.752 0 0 1-3.543 10.903l-123.89 90.012 113.119-144.97z" fill="#FCA326" />
|
||||
<path d="M241.194 91.105h-66.015l28.37-87.315c1.46-4.493 7.816-4.492 9.275 0l28.37 87.315z" fill="#E24329" />
|
||||
</Icon>
|
||||
)
|
@ -1,4 +1,5 @@
|
||||
export * from './GiphyLogo'
|
||||
export * from './GitlabLogo'
|
||||
export * from './GoogleAnalyticsLogo'
|
||||
export * from './GoogleSheetsLogo'
|
||||
export * from './GtmLogo'
|
||||
|
@ -4,7 +4,7 @@ import { signIn, useSession } from 'next-auth/react'
|
||||
import { useRouter } from 'next/router'
|
||||
import React from 'react'
|
||||
import { stringify } from 'qs'
|
||||
import { FacebookLogo, GoogleLogo } from 'assets/logos'
|
||||
import { FacebookLogo, GoogleLogo, GitlabLogo } from 'assets/logos'
|
||||
|
||||
export const SocialLoginButtons = () => {
|
||||
const { query } = useRouter()
|
||||
@ -25,6 +25,11 @@ export const SocialLoginButtons = () => {
|
||||
callbackUrl: `/typebots?${stringify(query)}`,
|
||||
})
|
||||
|
||||
const handleGitlabClick = async () =>
|
||||
signIn('gitlab', {
|
||||
callbackUrl: `/typebots?${stringify(query)}`,
|
||||
})
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
{process.env.NEXT_PUBLIC_GITHUB_CLIENT_ID && (
|
||||
@ -60,6 +65,17 @@ export const SocialLoginButtons = () => {
|
||||
Continue with Facebook
|
||||
</Button>
|
||||
)}
|
||||
{process.env.NEXT_PUBLIC_GITLAB_CLIENT_ID && (
|
||||
<Button
|
||||
leftIcon={<GitlabLogo />}
|
||||
onClick={handleGitlabClick}
|
||||
data-testid="gitlab"
|
||||
isLoading={['loading', 'authenticated'].includes(status)}
|
||||
variant="outline"
|
||||
>
|
||||
Continue with {process.env.NEXT_PUBLIC_GITLAB_NAME || 'GitLab'}
|
||||
</Button>
|
||||
)}
|
||||
</Stack>
|
||||
)
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import NextAuth from 'next-auth'
|
||||
import NextAuth, { Account } from 'next-auth'
|
||||
import EmailProvider from 'next-auth/providers/email'
|
||||
import GitHubProvider from 'next-auth/providers/github'
|
||||
import GitlabProvider from 'next-auth/providers/gitlab'
|
||||
import GoogleProvider from 'next-auth/providers/google'
|
||||
import FacebookProvider from 'next-auth/providers/facebook'
|
||||
import prisma from 'libs/prisma'
|
||||
@ -60,6 +61,22 @@ if (
|
||||
})
|
||||
)
|
||||
|
||||
if (
|
||||
process.env.NEXT_PUBLIC_GITLAB_CLIENT_ID &&
|
||||
process.env.GITLAB_CLIENT_SECRET
|
||||
) {
|
||||
const BASE_URL = process.env.GITLAB_BASE_URL || 'https://gitlab.com'
|
||||
providers.push(
|
||||
GitlabProvider({
|
||||
clientId: process.env.NEXT_PUBLIC_GITLAB_CLIENT_ID,
|
||||
clientSecret: process.env.GITLAB_CLIENT_SECRET,
|
||||
authorization: `${BASE_URL}/oauth/authorize?scope=read_api`,
|
||||
token: `${BASE_URL}/oauth/token`,
|
||||
userinfo: `${BASE_URL}/api/v4/user`,
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
const handler = (req: NextApiRequest, res: NextApiResponse) => {
|
||||
if (req.method === 'HEAD') {
|
||||
res.status(200)
|
||||
@ -81,6 +98,14 @@ const handler = (req: NextApiRequest, res: NextApiResponse) => {
|
||||
user: userFromDb,
|
||||
}
|
||||
},
|
||||
signIn: async ({ account }) => {
|
||||
const requiredGroups = getRequiredGroups(account.provider)
|
||||
if (requiredGroups.length > 0) {
|
||||
const userGroups = await getUserGroups(account)
|
||||
return checkHasGroups(userGroups, requiredGroups)
|
||||
}
|
||||
return true
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
@ -98,4 +123,31 @@ const updateLastActivityDate = async (user: User) => {
|
||||
})
|
||||
}
|
||||
|
||||
const getUserGroups = async (account: Account): Promise<string[]> => {
|
||||
switch (account.provider) {
|
||||
case 'gitlab': {
|
||||
const res = await fetch(
|
||||
`${process.env.GITLAB_BASE_URL || 'https://gitlab.com'}/api/v4/groups`,
|
||||
{ headers: { Authorization: `Bearer ${account.access_token}` } }
|
||||
)
|
||||
const userGroups = await res.json()
|
||||
return userGroups.map((group: { full_path: string }) => group.full_path)
|
||||
}
|
||||
default:
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
const getRequiredGroups = (provider: string): string[] => {
|
||||
switch (provider) {
|
||||
case 'gitlab':
|
||||
return process.env.GITLAB_REQUIRED_GROUPS?.split(',') || []
|
||||
default:
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
const checkHasGroups = (userGroups: string[], requiredGroups: string[]) =>
|
||||
userGroups?.some((userGroup) => requiredGroups?.includes(userGroup))
|
||||
|
||||
export default withSentry(handler)
|
||||
|
@ -80,6 +80,23 @@ You can create your own GitHub OAuth app [here](https://github.com/settings/deve
|
||||
|
||||
</p></details>
|
||||
|
||||
<details><summary><h3>GitLab (Auth)</h3></summary>
|
||||
<p>
|
||||
|
||||
Used for authenticating with GitLab.
|
||||
Follow the official GitLab guide for creating OAuth2 applications [here](https://docs.gitlab.com/ee/integration/oauth_provider.html).
|
||||
The Authorization callback URL should be `$NEXTAUTH_URL/api/auth/callback/gitlab`
|
||||
|
||||
| Parameter | Default | Description |
|
||||
| ---------------------------- | ------------------ | ------------------------------------------------------------------------------------ | --- |
|
||||
| NEXT_PUBLIC_GITLAB_CLIENT_ID | -- | Application client ID. Also used to check if it is enabled in the front-end |
|
||||
| GITLAB_CLIENT_SECRET | -- | Application secret |
|
||||
| GITLAB_BASE_URL | https://gitlab.com | Base URL of the GitLab instance | |
|
||||
| GITLAB_REQUIRED_GROUPS | -- | Comma-separated list of groups the user has to be a direct member of, e.g. `foo,bar` |
|
||||
| NEXT_PUBLIC_GITLAB_NAME | GitLab | Name of the GitLab instance, used for the SSO Login Button |
|
||||
|
||||
</p></details>
|
||||
|
||||
<details><summary><h3>Facebook (Auth)</h3></summary>
|
||||
<p>
|
||||
|
||||
|
Reference in New Issue
Block a user