mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-04 21:04:37 +08:00
add bitbucket oauth (#223)
* add bitbucket oauth * updated button style * fixed docs --------- Co-authored-by: Zai Shi <zaishi00@outlook.com>
This commit is contained in:
parent
f60508031e
commit
bba2b1884d
@ -0,0 +1,2 @@
|
||||
-- AlterEnum
|
||||
ALTER TYPE "StandardOAuthProviderType" ADD VALUE 'BITBUCKET';
|
||||
@ -581,6 +581,7 @@ enum StandardOAuthProviderType {
|
||||
SPOTIFY
|
||||
DISCORD
|
||||
GITLAB
|
||||
BITBUCKET
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
@ -12,6 +12,7 @@ import { SpotifyProvider } from "./providers/spotify";
|
||||
import { MockProvider } from "./providers/mock";
|
||||
import { DiscordProvider } from "@/oauth/providers/discord";
|
||||
import { GitlabProvider } from "./providers/gitlab";
|
||||
import { BitbucketProvider } from "./providers/bitbucket";
|
||||
|
||||
const _providers = {
|
||||
github: GithubProvider,
|
||||
@ -21,6 +22,7 @@ const _providers = {
|
||||
spotify: SpotifyProvider,
|
||||
discord: DiscordProvider,
|
||||
gitlab: GitlabProvider,
|
||||
bitbucket: BitbucketProvider,
|
||||
} as const;
|
||||
|
||||
const mockProvider = MockProvider;
|
||||
|
||||
48
apps/backend/src/oauth/providers/bitbucket.tsx
Normal file
48
apps/backend/src/oauth/providers/bitbucket.tsx
Normal file
@ -0,0 +1,48 @@
|
||||
import { OAuthBaseProvider, TokenSet } from "./base";
|
||||
import { OAuthUserInfo, validateUserInfo } from "../utils";
|
||||
import { getEnvVariable } from "@stackframe/stack-shared/dist/utils/env";
|
||||
|
||||
export class BitbucketProvider extends OAuthBaseProvider {
|
||||
private constructor(
|
||||
...args: ConstructorParameters<typeof OAuthBaseProvider>
|
||||
) {
|
||||
super(...args);
|
||||
}
|
||||
|
||||
static async create(options: { clientId: string, clientSecret: string }) {
|
||||
return new BitbucketProvider(
|
||||
...(await OAuthBaseProvider.createConstructorArgs({
|
||||
issuer: "https://bitbucket.org",
|
||||
authorizationEndpoint: "https://bitbucket.org/site/oauth2/authorize",
|
||||
tokenEndpoint: "https://bitbucket.org/site/oauth2/access_token",
|
||||
redirectUri:
|
||||
getEnvVariable("STACK_BASE_URL") +
|
||||
"/api/v1/auth/oauth/callback/bitbucket",
|
||||
baseScope: "account email",
|
||||
...options,
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
async postProcessUserInfo(tokenSet: TokenSet): Promise<OAuthUserInfo> {
|
||||
const headers = {
|
||||
Authorization: `Bearer ${tokenSet.accessToken}`,
|
||||
};
|
||||
const [userInfo, emailData] = await Promise.all([
|
||||
fetch("https://api.bitbucket.org/2.0/user", { headers }).then((res) =>
|
||||
res.json()
|
||||
),
|
||||
fetch("https://api.bitbucket.org/2.0/user/emails", { headers }).then(
|
||||
(res) => res.json()
|
||||
),
|
||||
]);
|
||||
|
||||
return validateUserInfo({
|
||||
accountId: userInfo.account_id,
|
||||
displayName: userInfo.display_name,
|
||||
email: emailData?.values[0].email,
|
||||
profileImageUrl: userInfo.links.avatar.href,
|
||||
emailVerified: emailData?.values[0].is_confirmed,
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -11,7 +11,7 @@ import * as yup from "yup";
|
||||
|
||||
export const projectFormSchema = yup.object({
|
||||
displayName: yup.string().min(1, "Display name is required").required(),
|
||||
signInMethods: yup.array(yup.string().oneOf(["google", "github", "microsoft", "facebook", "credential", "magicLink", "discord", "gitlab"]).required()).required(),
|
||||
signInMethods: yup.array(yup.string().oneOf(["google", "github", "microsoft", "facebook", "credential", "magicLink", "discord", "gitlab", "bitbucket"]).required()).required(),
|
||||
});
|
||||
|
||||
export type ProjectFormValues = yup.InferType<typeof projectFormSchema>
|
||||
|
||||
@ -24,6 +24,7 @@ function toTitle(id: string) {
|
||||
spotify: "Spotify",
|
||||
discord: "Discord",
|
||||
gitlab: "GitLab",
|
||||
bitbucket: "Bitbucket",
|
||||
}[id];
|
||||
}
|
||||
|
||||
|
||||
@ -10,6 +10,7 @@ const mockedProviders = [
|
||||
"spotify",
|
||||
"discord",
|
||||
"gitlab",
|
||||
"bitbucket",
|
||||
];
|
||||
|
||||
const configuration: Configuration = {
|
||||
|
||||
@ -53,6 +53,11 @@ To use your own OAuth provider setups in production, follow these steps for each
|
||||
Callback URL:
|
||||
`https://api.stack-auth.com/api/v1/auth/oauth/callback/gitlab`
|
||||
</Tab>
|
||||
<Tab title="Bitbucket">
|
||||
[Bitbucket OAuth Setup Guide](https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud)
|
||||
Callback URL:
|
||||
`https://api.stack-auth.com/api/v1/auth/oauth/callback/bitbucket`
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
2. **Enter OAuth Credentials**: Go to the `Auth Methods` section in the Stack dashboard, open the provider's settings, switch from shared keys to custom keys, and enter the client ID and client secret.
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
export const standardProviders = ["google", "github", "facebook", "microsoft", "spotify", "discord", "gitlab"] as const;
|
||||
export const standardProviders = ["google", "github", "facebook", "microsoft", "spotify", "discord", "gitlab", "bitbucket"] as const;
|
||||
// No more shared providers should be added except for special cases
|
||||
export const sharedProviders = ["google", "github", "facebook", "microsoft", "spotify"] as const;
|
||||
export const allProviders = ["google", "github", "facebook", "microsoft", "spotify", "discord", "gitlab"] as const;
|
||||
export const allProviders = ["google", "github", "facebook", "microsoft", "spotify", "discord", "gitlab", "bitbucket"] as const;
|
||||
|
||||
export type ProviderType = typeof allProviders[number];
|
||||
export type StandardProviderType = typeof standardProviders[number];
|
||||
|
||||
@ -72,39 +72,45 @@ function GitlabIcon({ iconSize } : { iconSize: number} ) {
|
||||
preserveAspectRatio="xMidYMid"
|
||||
>
|
||||
<g>
|
||||
<path
|
||||
d="M128.07485,236.074667 L128.07485,236.074667 L175.17885,91.1043048 L80.9708495,91.1043048 L128.07485,236.074667 L128.07485,236.074667 Z"
|
||||
fill="#E24329"
|
||||
></path>
|
||||
<path
|
||||
d="M128.07485,236.074423 L80.9708495,91.104061 L14.9557638,91.104061 L128.07485,236.074423 L128.07485,236.074423 Z"
|
||||
fill="#FC6D26"
|
||||
></path>
|
||||
<path
|
||||
d="M14.9558857,91.1044267 L14.9558857,91.1044267 L0.641828571,135.159589 C-0.663771429,139.17757 0.766171429,143.57955 4.18438095,146.06275 L128.074971,236.074789 L14.9558857,91.1044267 L14.9558857,91.1044267 Z"
|
||||
fill="#FCA326"
|
||||
></path>
|
||||
<path
|
||||
d="M14.9558857,91.1045486 L80.9709714,91.1045486 L52.6000762,3.79026286 C51.1408762,-0.703146667 44.7847619,-0.701927619 43.3255619,3.79026286 L14.9558857,91.1045486 L14.9558857,91.1045486 Z"
|
||||
fill="#E24329"
|
||||
></path>
|
||||
<path
|
||||
d="M128.07485,236.074423 L175.17885,91.104061 L241.193935,91.104061 L128.07485,236.074423 L128.07485,236.074423 Z"
|
||||
fill="#FC6D26"
|
||||
></path>
|
||||
<path
|
||||
d="M241.193935,91.1044267 L241.193935,91.1044267 L255.507992,135.159589 C256.813592,139.17757 255.38365,143.57955 251.96544,146.06275 L128.07485,236.074789 L241.193935,91.1044267 L241.193935,91.1044267 Z"
|
||||
fill="#FCA326"
|
||||
></path>
|
||||
<path
|
||||
d="M241.193935,91.1045486 L175.17885,91.1045486 L203.549745,3.79026286 C205.008945,-0.703146667 211.365059,-0.701927619 212.824259,3.79026286 L241.193935,91.1045486 L241.193935,91.1045486 Z"
|
||||
fill="#E24329"
|
||||
></path>
|
||||
<path d="M128.07485,236.074667 L128.07485,236.074667 L175.17885,91.1043048 L80.9708495,91.1043048 L128.07485,236.074667 L128.07485,236.074667 Z" fill="#E24329"></path>
|
||||
<path d="M128.07485,236.074423 L80.9708495,91.104061 L14.9557638,91.104061 L128.07485,236.074423 L128.07485,236.074423 Z" fill="#FC6D26"></path>
|
||||
<path d="M14.9558857,91.1044267 L14.9558857,91.1044267 L0.641828571,135.159589 C-0.663771429,139.17757 0.766171429,143.57955 4.18438095,146.06275 L128.074971,236.074789 L14.9558857,91.1044267 L14.9558857,91.1044267 Z" fill="#FCA326"></path>
|
||||
<path d="M14.9558857,91.1045486 L80.9709714,91.1045486 L52.6000762,3.79026286 C51.1408762,-0.703146667 44.7847619,-0.701927619 43.3255619,3.79026286 L14.9558857,91.1045486 L14.9558857,91.1045486 Z" fill="#E24329"></path>
|
||||
<path d="M128.07485,236.074423 L175.17885,91.104061 L241.193935,91.104061 L128.07485,236.074423 L128.07485,236.074423 Z" fill="#FC6D26"></path>
|
||||
<path d="M241.193935,91.1044267 L241.193935,91.1044267 L255.507992,135.159589 C256.813592,139.17757 255.38365,143.57955 251.96544,146.06275 L128.07485,236.074789 L241.193935,91.1044267 L241.193935,91.1044267 Z" fill="#FCA326"></path>
|
||||
<path d="M241.193935,91.1045486 L175.17885,91.1045486 L203.549745,3.79026286 C205.008945,-0.703146667 211.365059,-0.701927619 212.824259,3.79026286 L241.193935,91.1045486 L241.193935,91.1045486 Z" fill="#E24329"></path>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function BitbucketIcon({ iconSize }: { iconSize: number }) {
|
||||
return (
|
||||
<svg
|
||||
preserveAspectRatio="xMidYMid"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="-0.9662264221278978 -0.5824607696358868 257.93281329857973 230.8324730411935"
|
||||
width={iconSize}
|
||||
height={iconSize}
|
||||
>
|
||||
<linearGradient
|
||||
id="a"
|
||||
x1="108.633%"
|
||||
x2="46.927%"
|
||||
y1="13.818%"
|
||||
y2="78.776%"
|
||||
>
|
||||
<stop offset=".18" stopColor="#0052cc" />
|
||||
<stop offset="1" stopColor="#2684ff" />
|
||||
</linearGradient>
|
||||
<g fill="none">
|
||||
<path d="M101.272 152.561h53.449l12.901-75.32H87.06z" />
|
||||
<path d="M8.308 0A8.202 8.202 0 0 0 .106 9.516l34.819 211.373a11.155 11.155 0 0 0 10.909 9.31h167.04a8.202 8.202 0 0 0 8.201-6.89l34.82-213.752a8.202 8.202 0 0 0-8.203-9.514zm146.616 152.768h-53.315l-14.436-75.42h80.67z" fill="#2684ff"/>
|
||||
<path d="M244.61 77.242h-76.916l-12.909 75.36h-53.272l-62.902 74.663a11.105 11.105 0 0 0 7.171 2.704H212.73a8.196 8.196 0 0 0 8.196-6.884z" fill="url(#a)"/>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
const changeColor = (c: Color, value: number) => {
|
||||
if (c.isLight()) {
|
||||
@ -197,6 +203,16 @@ export function OAuthButton({
|
||||
};
|
||||
break;
|
||||
}
|
||||
case "bitbucket": {
|
||||
style = {
|
||||
backgroundColor: "#fff",
|
||||
textColor: "#000",
|
||||
border: "1px solid #ddd",
|
||||
name: "Bitbucket",
|
||||
icon: <BitbucketIcon iconSize={iconSize} />,
|
||||
};
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
style = {
|
||||
name: provider,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user