1 line
12 KiB
JavaScript
1 line
12 KiB
JavaScript
"use strict";(self.webpackChunkpingvindocs=self.webpackChunkpingvindocs||[]).push([[819],{3403:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>c,contentTitle:()=>s,default:()=>a,frontMatter:()=>t,metadata:()=>d,toc:()=>l});var o=i(4848),r=i(8453);const t={id:"oauth2login"},s="OAuth 2 Login Guide",d={id:"setup/oauth2login",title:"OAuth 2 Login Guide",description:"Config Built-in OAuth 2 Providers",source:"@site/docs/setup/oauth2login.md",sourceDirName:"setup",slug:"/setup/oauth2login",permalink:"/pingvin-share/setup/oauth2login",draft:!1,unlisted:!1,editUrl:"https://github.com/stonith404/pingvin-share/edit/main/docs/docs/setup/oauth2login.md",tags:[],version:"current",frontMatter:{id:"oauth2login"},sidebar:"docsSidebar",previous:{title:"Integrations",permalink:"/pingvin-share/setup/integrations"},next:{title:"Upgrading",permalink:"/pingvin-share/setup/upgrading"}},c={},l=[{value:"Config Built-in OAuth 2 Providers",id:"config-built-in-oauth-2-providers",level:2},{value:"GitHub",id:"github",level:3},{value:"Google",id:"google",level:3},{value:"Microsoft",id:"microsoft",level:3},{value:"Discord",id:"discord",level:3},{value:"OpenID Connect",id:"openid-connect",level:3},{value:"Custom your OAuth 2 Provider",id:"custom-your-oauth-2-provider",level:2},{value:"1. Create config",id:"1-create-config",level:3},{value:"2. Create provider class",id:"2-create-provider-class",level:3},{value:"Generic OpenID Connect",id:"generic-openid-connect",level:4},{value:"OAuth 2",id:"oauth-2",level:4},{value:"3. Register provider",id:"3-register-provider",level:3},{value:"4. Add frontend icon",id:"4-add-frontend-icon",level:3},{value:"5. Add i18n text",id:"5-add-i18n-text",level:3}];function h(e){const n={a:"a",blockquote:"blockquote",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.header,{children:(0,o.jsx)(n.h1,{id:"oauth-2-login-guide",children:"OAuth 2 Login Guide"})}),"\n",(0,o.jsx)(n.h2,{id:"config-built-in-oauth-2-providers",children:"Config Built-in OAuth 2 Providers"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#github",children:"GitHub"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#google",children:"Google"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#microsoft",children:"Microsoft"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#discord",children:"Discord"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"#openid-connect",children:"OpenID Connect"})}),"\n"]}),"\n",(0,o.jsx)(n.h3,{id:"github",children:"GitHub"}),"\n",(0,o.jsxs)(n.p,{children:["Please follow the ",(0,o.jsx)(n.a,{href:"https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/creating-an-oauth-app",children:"official guide"})," to create an OAuth app."]}),"\n",(0,o.jsxs)(n.p,{children:["Redirect URL: ",(0,o.jsx)(n.code,{children:"https://<your-domain>/api/oauth/callback/github"})]}),"\n",(0,o.jsx)(n.h3,{id:"google",children:"Google"}),"\n",(0,o.jsxs)(n.p,{children:["Please follow the ",(0,o.jsx)(n.a,{href:"https://developers.google.com/identity/protocols/oauth2/web-server#prerequisites",children:"official guide"})," to create an OAuth 2.0 App."]}),"\n",(0,o.jsxs)(n.p,{children:["Redirect URL: ",(0,o.jsx)(n.code,{children:"https://<your-domain>/api/oauth/callback/google"})]}),"\n",(0,o.jsx)(n.h3,{id:"microsoft",children:"Microsoft"}),"\n",(0,o.jsxs)(n.p,{children:["Please follow the ",(0,o.jsx)(n.a,{href:"https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app",children:"official guide"})," to register an application."]}),"\n",(0,o.jsxs)(n.blockquote,{children:["\n",(0,o.jsxs)(n.p,{children:["[!IMPORTANT] > ",(0,o.jsx)(n.strong,{children:"Microsoft Tenant"})," you set in the admin panel must match the ",(0,o.jsx)(n.strong,{children:"supported account types"})," you set in the Microsoft Entra admin center, otherwise the OAuth login will not work. Refer to the ",(0,o.jsx)(n.a,{href:"https://learn.microsoft.com/en-us/entra/identity-platform/v2-protocols-oidc#find-your-apps-openid-configuration-document-uri",children:"official documentation"})," for more details."]}),"\n"]}),"\n",(0,o.jsxs)(n.p,{children:["Redirect URL: ",(0,o.jsx)(n.code,{children:"https://<your-domain>/api/oauth/callback/microsoft"})]}),"\n",(0,o.jsx)(n.h3,{id:"discord",children:"Discord"}),"\n",(0,o.jsxs)(n.p,{children:["Create an application on ",(0,o.jsx)(n.a,{href:"https://discord.com/developers/applications",children:"Discord Developer Portal"}),"."]}),"\n",(0,o.jsxs)(n.p,{children:["Redirect URL: ",(0,o.jsx)(n.code,{children:"https://<your-domain>/api/oauth/callback/discord"})]}),"\n",(0,o.jsx)(n.h3,{id:"openid-connect",children:"OpenID Connect"}),"\n",(0,o.jsxs)(n.p,{children:["Generic OpenID Connect provider is also supported, we have tested it on Keycloak, Authentik, Casdoor and ",(0,o.jsx)(n.a,{href:"https://github.com/stonith404/pocket-id",children:"Pocket ID"}),"."]}),"\n",(0,o.jsxs)(n.p,{children:["Redirect URI: ",(0,o.jsx)(n.code,{children:"https://<your-domain>/api/oauth/callback/oidc"})]}),"\n",(0,o.jsxs)(n.p,{children:["Post Logout Redirect URI: ",(0,o.jsx)(n.code,{children:"https://<your-domain>"})]}),"\n",(0,o.jsx)(n.h2,{id:"custom-your-oauth-2-provider",children:"Custom your OAuth 2 Provider"}),"\n",(0,o.jsx)(n.p,{children:"If our built-in providers don't meet your needs, you can create your own OAuth 2 provider."}),"\n",(0,o.jsx)(n.h3,{id:"1-create-config",children:"1. Create config"}),"\n",(0,o.jsxs)(n.p,{children:["Add your config (client id, client secret, etc.) in ",(0,o.jsx)(n.a,{href:"https://github.com/stonith404/pingvin-share/blob/main/backend/prisma/seed/config.seed.ts",children:(0,o.jsx)(n.code,{children:"config.seed.ts"})}),":"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-ts",children:'const configVariables: ConfigVariables = {\n // ...\n oauth: {\n // ...\n "YOUR_PROVIDER_NAME-enabled": {\n type: "boolean",\n defaultValue: "false",\n },\n "YOUR_PROVIDER_NAME-clientId": {\n type: "string",\n defaultValue: "",\n },\n "YOUR_PROVIDER_NAME-clientSecret": {\n type: "string",\n defaultValue: "",\n obscured: true,\n },\n },\n};\n'})}),"\n",(0,o.jsx)(n.h3,{id:"2-create-provider-class",children:"2. Create provider class"}),"\n",(0,o.jsx)(n.h4,{id:"generic-openid-connect",children:"Generic OpenID Connect"}),"\n",(0,o.jsxs)(n.p,{children:["If your provider supports OpenID connect, it's extremely easy to extend ",(0,o.jsx)(n.a,{href:"https://github.com/stonith404/pingvin-share/blob/main/backend/src/oauth/provider/genericOidc.provider.ts",children:(0,o.jsx)(n.code,{children:"GenericOidcProvider"})})," to add a new OpenID Connect provider."]}),"\n",(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.a,{href:"https://github.com/stonith404/pingvin-share/blob/main/backend/src/oauth/provider/google.provider.ts",children:"Google provider"})," and ",(0,o.jsx)(n.a,{href:"https://github.com/stonith404/pingvin-share/blob/main/backend/src/oauth/provider/microsoft.provider.ts",children:"Microsoft provider"})," are good examples."]}),"\n",(0,o.jsx)(n.p,{children:"Here are some discovery URIs for popular providers:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:["Microsoft: ",(0,o.jsx)(n.code,{children:"https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration"})]}),"\n",(0,o.jsxs)(n.li,{children:["Google: ",(0,o.jsx)(n.code,{children:"https://accounts.google.com/.well-known/openid-configuration"})]}),"\n",(0,o.jsxs)(n.li,{children:["Apple: ",(0,o.jsx)(n.code,{children:"https://appleid.apple.com/.well-known/openid-configuration"})]}),"\n",(0,o.jsxs)(n.li,{children:["Gitlab: ",(0,o.jsx)(n.code,{children:"https://gitlab.com/.well-known/openid-configuration"})]}),"\n",(0,o.jsxs)(n.li,{children:["Huawei: ",(0,o.jsx)(n.code,{children:"https://oauth-login.cloud.huawei.com/.well-known/openid-configuration"})]}),"\n",(0,o.jsxs)(n.li,{children:["Paypal: ",(0,o.jsx)(n.code,{children:"https://www.paypal.com/.well-known/openid-configuration"})]}),"\n",(0,o.jsxs)(n.li,{children:["Yahoo: ",(0,o.jsx)(n.code,{children:"https://api.login.yahoo.com/.well-known/openid-configuration"})]}),"\n"]}),"\n",(0,o.jsx)(n.h4,{id:"oauth-2",children:"OAuth 2"}),"\n",(0,o.jsxs)(n.p,{children:["If your provider only supports OAuth 2, you can implement ",(0,o.jsx)(n.a,{href:"https://github.com/stonith404/pingvin-share/blob/main/backend/src/oauth/provider/oauthProvider.interface.ts",children:(0,o.jsx)(n.code,{children:"OAuthProvider"})})," interface to add a new OAuth 2 provider."]}),"\n",(0,o.jsxs)(n.p,{children:["The ",(0,o.jsx)(n.a,{href:"https://github.com/stonith404/pingvin-share/blob/main/backend/src/oauth/provider/github.provider.ts",children:"GitHub provider"})," and ",(0,o.jsx)(n.a,{href:"https://github.com/stonith404/pingvin-share/blob/main/backend/src/oauth/provider/discord.provider.ts",children:"Discord provider"})," are good examples."]}),"\n",(0,o.jsx)(n.h3,{id:"3-register-provider",children:"3. Register provider"}),"\n",(0,o.jsxs)(n.p,{children:["Register your provider in ",(0,o.jsx)(n.a,{href:"https://github.com/stonith404/pingvin-share/blob/main/backend/src/oauth/oauth.module.ts",children:(0,o.jsx)(n.code,{children:"OAuthModule"})})," and ",(0,o.jsx)(n.a,{href:"https://github.com/stonith404/pingvin-share/blob/main/backend/src/oauth/dto/oauthSignIn.dto.ts",children:(0,o.jsx)(n.code,{children:"OAuthSignInDto"})}),":"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-ts",children:'@Module({\n providers: [\n GitHubProvider,\n // your provider\n {\n provide: "OAUTH_PROVIDERS",\n useFactory(\n github: GitHubProvider /* your provider */\n ): Record<string, OAuthProvider<unknown>> {\n return {\n github,\n /* your provider */\n };\n },\n inject: [GitHubProvider /* your provider */],\n },\n ],\n})\nexport class OAuthModule {}\n'})}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-ts",children:'export interface OAuthSignInDto {\n provider:\n | "github"\n | "google"\n | "microsoft"\n | "discord"\n | "oidc" /* your provider*/;\n providerId: string;\n providerUsername: string;\n email: string;\n}\n'})}),"\n",(0,o.jsx)(n.h3,{id:"4-add-frontend-icon",children:"4. Add frontend icon"}),"\n",(0,o.jsxs)(n.p,{children:["Add an icon in ",(0,o.jsx)(n.a,{href:"https://github.com/stonith404/pingvin-share/blob/main/frontend/src/utils/oauth.util.tsx",children:(0,o.jsx)(n.code,{children:"oauth.util.tsx"})}),"."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-tsx",children:"const getOAuthIcon = (provider: string) => {\n return {\n github: <SiGithub />,\n /* your provider */\n }[provider];\n};\n"})}),"\n",(0,o.jsx)(n.h3,{id:"5-add-i18n-text",children:"5. Add i18n text"}),"\n",(0,o.jsxs)(n.p,{children:["Add keys below to your i18n text in ",(0,o.jsx)(n.a,{href:"https://github.com/stonith404/pingvin-share/blob/main/frontend/src/i18n/translations/en-US.ts",children:"locale file"}),"."]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.code,{children:"signIn.oauth.YOUR_PROVIDER_NAME"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.code,{children:"account.card.oauth.YOUR_PROVIDER_NAME"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.code,{children:"admin.config.oauth.YOUR_PROVIDER_NAME-enabled"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.code,{children:"admin.config.oauth.YOUR_PROVIDER_NAME-client-id"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.code,{children:"admin.config.oauth.YOUR_PROVIDER_NAME-client-secret"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.code,{children:"error.param.provider_YOUR_PROVIDER_NAME"})}),"\n",(0,o.jsx)(n.li,{children:"Other config keys you defined in step 1"}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"Congratulations! \ud83c\udf89 You have successfully added a new OAuth 2 provider! Pull requests are welcome if you want to share your provider with others."})]})}function a(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(h,{...e})}):h(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>s,x:()=>d});var o=i(6540);const r={},t=o.createContext(r);function s(e){const n=o.useContext(t);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),o.createElement(t.Provider,{value:n},e.children)}}}]); |