Skip to content

Commit

Permalink
Merge pull request #847 from supertokens/feat/oauth
Browse files Browse the repository at this point in the history
Add OAuth docs
  • Loading branch information
bcbogdan authored Oct 25, 2024
2 parents 8dc9d17 + 349af24 commit 2ef7a46
Show file tree
Hide file tree
Showing 253 changed files with 7,313 additions and 1,815 deletions.
31 changes: 25 additions & 6 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ version: 2.1
orbs:
node: circleci/[email protected]
slack: circleci/[email protected]

jobs:
deploy-to-test-site:
docker:
Expand All @@ -11,7 +10,7 @@ jobs:
steps:
- checkout
- node/install-packages:
app-dir: '~/project/v2'
app-dir: "~/project/v2"
- run: cd ../ && git clone [email protected]:supertokens/supertokens-backend-website.git
- run: apt-get update
- run: apt -y --fix-broken install
Expand All @@ -26,27 +25,27 @@ jobs:
steps:
- checkout
- node/install-packages:
app-dir: '~/project/v2'
app-dir: "~/project/v2"
- run:
name: Setup iOS env
command: cd v2/src/plugins/codeTypeChecking/iosEnv/ && pod install
no_output_timeout: 30m
- run: nvm install 16 -y
- run:
- run:
no_output_timeout: 30m
name: Run build for iOS docs
command: nvm use 16 && cd v2 && npm run build:ios
- slack/status
code-checking:
environment:
TAR_OPTIONS: --no-same-owner
TAR_OPTIONS: --no-same-owner
docker:
- image: rishabhpoddar/supertokens_docs_building_with_android
resource_class: xlarge
steps:
- checkout
- node/install-packages:
app-dir: '~/project/v2'
app-dir: "~/project/v2"
- run: cd ../ && git clone https://github.com/flutter/flutter.git
- run: cd ../ && export PATH="$PATH:/root/flutter/bin" && echo $PATH
- run: cd ../ && export PATH="$PATH:/root/flutter/bin" && flutter doctor && chown -R root:root /root/flutter
Expand All @@ -69,6 +68,26 @@ jobs:
name: Setup Dart Env
command: cd v2/src/plugins/codeTypeChecking/dart_env && export PATH="$PATH:/root/flutter/bin" && flutter pub get
no_output_timeout: 30m
- run:
name: Install Java
command: |
apt-get update
apt-get install -y openjdk-11-jdk
wget https://archive.apache.org/dist/maven/maven-3/3.8.4/binaries/apache-maven-3.8.4-bin.tar.gz
tar xzf apache-maven-3.8.4-bin.tar.gz
mv apache-maven-3.8.4 /opt/maven
echo 'export PATH=/opt/maven/bin:$PATH' >> $BASH_ENV
source $BASH_ENV
- run:
name: Install .NET
command: |
wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
dpkg -i packages-microsoft-prod.deb
rm packages-microsoft-prod.deb
apt-get update
apt-get install -y apt-transport-https
apt-get update
apt-get install -y dotnet-sdk-6.0
- run:
command: export PATH="$PATH:/root/flutter/bin" && cd v2 && npm run build
no_output_timeout: 30m
Expand Down
5 changes: 5 additions & 0 deletions v2/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,8 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*

src/plugins/codeTypeChecking/javaEnv/snippets/*
src/plugins/codeTypeChecking/phpEnv/snippets/*
src/plugins/codeTypeChecking/pythonEnv/snippets/*
src/plugins/codeTypeChecking/csharpEnv/snippets/*
10 changes: 5 additions & 5 deletions v2/attackprotectionsuite/backend-setup.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -505,8 +505,8 @@ SuperTokens.init({

const actionType = 'emailpassword-sign-up';
const ip = getIpFromRequest(input.options.req.original);
let email = input.formFields.filter((f) => f.id === "email")[0].value;
let password = input.formFields.filter((f) => f.id === "password")[0].value;
let email = input.formFields.filter((f) => f.id === "email")[0].value as string;
let password = input.formFields.filter((f) => f.id === "password")[0].value as string;
const bruteForceConfig = getBruteForceConfig(email, ip, actionType);

// we check the anomaly detection service before calling the original implementation of signUp
Expand All @@ -529,7 +529,7 @@ SuperTokens.init({

const actionType = 'emailpassword-sign-in';
const ip = getIpFromRequest(input.options.req.original);
let email = input.formFields.filter((f) => f.id === "email")[0].value;
let email = input.formFields.filter((f) => f.id === "email")[0].value as string;
const bruteForceConfig = getBruteForceConfig(email, ip, actionType);

// we check the anomaly detection service before calling the original implementation of signIn
Expand All @@ -552,7 +552,7 @@ SuperTokens.init({

const actionType = 'send-password-reset-email';
const ip = getIpFromRequest(input.options.req.original);
let email = input.formFields.filter((f) => f.id === "email")[0].value;
let email = input.formFields.filter((f) => f.id === "email")[0].value as string;
const bruteForceConfig = getBruteForceConfig(email, ip, actionType);

// we check the anomaly detection service before calling the original implementation of generatePasswordResetToken
Expand All @@ -564,7 +564,7 @@ SuperTokens.init({
return originalImplementation.generatePasswordResetTokenPOST!(input);
},
passwordResetPOST: async function (input) {
let password = input.formFields.filter((f) => f.id === "password")[0].value;
let password = input.formFields.filter((f) => f.id === "password")[0].value as string;
let securityCheckResponse = await handleSecurityChecks({ password });
if (securityCheckResponse !== undefined) {
return securityCheckResponse;
Expand Down
9 changes: 9 additions & 0 deletions v2/community/reusableMD/oauth-paid-banner.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import CustomAdmonition from "/src/components/customAdmonition"

<CustomAdmonition type="paid-feature">

This is a paid feature.

You can click on the **Enable Paid Features** button on [our dashboard](https://supertokens.com/dashboard-saas), and follow the steps from there on. Once enabled, this feature is free on the provided development environment.

</CustomAdmonition>
Empty file.
17 changes: 16 additions & 1 deletion v2/docusaurus.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ module.exports = {
},
prism: {
theme: require("prism-react-renderer/themes/vsDark"),
additionalLanguages: ["kotlin", "java", "swift", "dart"],
additionalLanguages: ["kotlin", "java", "swift", "dart", "csharp", "php"],
},
algolia: {
apiKey: "ce04a158637d345fc094ebbfa9a5156a",
Expand Down Expand Up @@ -256,6 +256,21 @@ module.exports = {
beforeDefaultRemarkPlugins,
},
],

[
"@docusaurus/plugin-content-docs",
{
id: "unified-login",
path: "unified-login",
routeBasePath: "docs/unified-login",
sidebarPath: require.resolve("./unified-login/sidebars.js"),
showLastUpdateTime: true,
editUrl: "https://github.com/supertokens/docs/tree/master/v2/",
remarkPlugins: remarkPlugins,
rehypePlugins: rehypePlugins,
beforeDefaultRemarkPlugins,
},
],
[
"@docusaurus/plugin-content-docs",
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ EmailPassword.init({
return {
...oI,
signUpPOST: async function (input) {
let email = input.formFields.find(i => i.id === "email")!.value;
let email = input.formFields.find(i => i.id === "email")!.value as string;

if (emailNotAllowed(email)) {
// highlight-start
Expand Down Expand Up @@ -186,4 +186,4 @@ emailpassword.init(override=emailpassword.InputOverrideConfig(apis=override_apis
```

</TabItem>
</BackendSDKTabs>
</BackendSDKTabs>
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ import { backendConfig } from "@/app/config/backend";
SuperTokens.init(backendConfig());

// in the app/api/auth/[...path]/route.ts file
const handleCall = getAppDirRequestHandler(NextResponse);
const handleCall = getAppDirRequestHandler();

const withCustomErrorHandling = async (request: NextRequest) => {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import TabItem from "@theme/TabItem";
import NpmOrScriptTabs from "/src/components/tabs/NpmOrScriptTabs"
import AngularUIImplementation from "/src/components/reusableSnippets/angularUIImplementation"
import VueUIImplementation from "/src/components/reusableSnippets/vueUIImplementation"
import { OAuthEmailVerificationDisclaimer }from "/src/components/OAuthDisclaimer"


# Enable email verification
Expand All @@ -25,6 +26,8 @@ import VueUIImplementation from "/src/components/reusableSnippets/vueUIImplement
Email verification is turned off by default. It is strongly encouraged to enable it to ensure the authenticity of your users.
:::

<OAuthEmailVerificationDisclaimer />

<PreBuiltOrCustomUISwitcher>

<PreBuiltUIContent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,14 @@ import NpmOrScriptTabs from "/src/components/tabs/NpmOrScriptTabs"
import AngularUIImplementation from "/src/components/reusableSnippets/angularUIImplementation"
import VueUIImplementation from "/src/components/reusableSnippets/vueUIImplementation"
import {Answer} from "/src/components/question"
import { OAuthEmailVerificationDisclaimer }from "/src/components/OAuthDisclaimer"

# Protecting backend APIs and website routes

## Protecting backend API routes

<OAuthEmailVerificationDisclaimer />

### Add email verification checks to all API routes

If you want to protect all your backend API routes with email verification checks, set the `mode` to `REQUIRED` in the `EmailVerification` config. Routes protected with the `verifySession` middleware will now additionally check for email verification status.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ SuperTokens.init({
let name = ""
for (let i = 0; i < input.formFields.length; i++) {
if (input.formFields[i].id == "name") {
name = input.formFields[i].value
name = input.formFields[i].value as string;
}
}

Expand Down Expand Up @@ -553,4 +553,4 @@ For example, when the frontend calls the email password sign up API, the SDK inv

Therefore, if you want to associate a role with a user, you would want to do that in the `Functions.SignUp` function since then those roles would get added to the session in the subsequent call to the `Session.createNewSession` function. If instead, you associate a role to the user in the `API.SignUpPOST` (after calling the original implementation), the role will not be automatically added to the session since the `Session.createNewSession` would have already been called before the original implementation returns.

The only time it makes sense to override the API functions is if you want to access an argument that's not available in the recipe function. For example, the custom form fields for email password sign up is an input to the `API.SignUpPOST`, but not to the `Functions.SignUp`, so if you want to access the form fields, you should override the `API.SignUpPOST` as shown above. You can also always add the formFields to the userContext object and read it later in the `Functions.SignUp` override, but then you would lose the typing of the form field array structure (which is not a runtime problem, but just a slightly bad developer experience).
The only time it makes sense to override the API functions is if you want to access an argument that's not available in the recipe function. For example, the custom form fields for email password sign up is an input to the `API.SignUpPOST`, but not to the `Functions.SignUp`, so if you want to access the form fields, you should override the `API.SignUpPOST` as shown above. You can also always add the formFields to the userContext object and read it later in the `Functions.SignUp` override, but then you would lose the typing of the form field array structure (which is not a runtime problem, but just a slightly bad developer experience).
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ import FrontendReactContextSubTabs from "/src/components/tabs/FrontendReactConte

# Option 1. Using the access token payload

:::caution

This guide describes how to add custom claims to **SuperTokens Access Tokens**.

If you are implementing [**Unified Login**](/docs/unified-login/introduction), which makes use of **OAuth2 Access Tokens**, you will have to check the separate [guide](/docs/unified-login/customizations/add-custom-claims-in-tokens).

:::

## Add custom claims to the access token payload

:::important
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ import FrontendReactContextSubTabs from "/src/components/tabs/FrontendReactConte

# Option 2. Using claim validators

:::caution

This guide describes how to add custom claims to **SuperTokens Access Tokens**.

If you are implementing [**Unified Login**](/docs/unified-login/introduction), which makes use of **OAuth2 Access Tokens**, you will have to check the separate [guide](/docs/unified-login/customizations/add-custom-claims-in-tokens).

:::

## What are session claims?
SuperTokens session has a property called `accessTokenPayload`. This is a `JSON` object that's stored in a user's session which can be accessed on the frontend and backend. The key-values in this JSON payload are called claims.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@ import FrontendPreBuiltUITabs from "/src/components/tabs/FrontendPreBuiltUITabs"
import FrontendCustomUITabs from "/src/components/tabs/FrontendCustomUITabs"
import NpmOrScriptTabs from "/src/components/tabs/NpmOrScriptTabs"
import FrontendMobileSubTabs from "/src/components/tabs/FrontendMobileSubTabs"
import { OAuthFrontendVerificationDisclaimer }from "/src/components/OAuthDisclaimer"

# Protecting frontend routes

<OAuthFrontendVerificationDisclaimer />

<PreBuiltOrCustomUISwitcher>

<PreBuiltUIContent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@ import NodeJSFrameworkSubTabs from "/src/components/tabs/NodeJSFrameworkSubTabs"
import PythonFrameworkSubTabs from "/src/components/tabs/PythonFrameworkSubTabs";
import PythonSyncAsyncSubTabs from "/src/components/tabs/PythonSyncAsyncSubTabs";
import TabItem from '@theme/TabItem';
import { OAuthVerifyTokensDisclaimer }from "/src/components/OAuthDisclaimer"


# Session Verification using `getSession`

<OAuthVerifyTokensDisclaimer />

If you want to use a non-middleware form of `verifySession`, you can use the `getSession` function.

## Using `getSession`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@ import BackendSDKTabs from "/src/components/tabs/BackendSDKTabs"
import NodeJSFrameworkSubTabs from "/src/components/tabs/NodeJSFrameworkSubTabs";
import PythonFrameworkSubTabs from "/src/components/tabs/PythonFrameworkSubTabs";
import TabItem from '@theme/TabItem';
import { OAuthVerifyTokensDisclaimer }from "/src/components/OAuthDisclaimer"
import GoFrameworkSubTabs from "/src/components/tabs/GoFrameworkSubTabs"

## Verifying a session using the `verifySession` middleware

<OAuthVerifyTokensDisclaimer />

For your APIs that require a user to be logged in, use the `verifySession` middleware:

<BackendSDKTabs>
Expand Down
3 changes: 3 additions & 0 deletions v2/emailpassword/common-customizations/sessions/ssr.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@ import NodeJSFrameworkSubTabs from "/src/components/tabs/NodeJSFrameworkSubTabs"
import PythonFrameworkSubTabs from "/src/components/tabs/PythonFrameworkSubTabs";
import PythonSyncAsyncSubTabs from "/src/components/tabs/PythonSyncAsyncSubTabs";
import TabItem from '@theme/TabItem';
import { OAuthVerifyTokensDisclaimer }from "/src/components/OAuthDisclaimer"

# Session verification during server side rendering

<OAuthVerifyTokensDisclaimer />

:::important
Getting access to the session during server side rendering is only possible using cookie-based sessions. This is the default setting, but you have to keep this in mind if you want to switch to header-based sessions.
:::
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,18 @@ import FrontendMobileSubTabs from "/src/components/tabs/FrontendMobileSubTabs"
import BackendSDKTabs from "/src/components/tabs/BackendSDKTabs";
import AppInfoForm from "/src/components/appInfoForm";
import TabItem from '@theme/TabItem';
import { OAuthVerifyTokensDisclaimer }from "/src/components/OAuthDisclaimer"

# Manually verify the JWT

<OAuthVerifyTokensDisclaimer />

There are three steps in doing session verification using JWTs:
- Verify the JWT signature and expiry using a JWT verification library
- Check for custom claim values for authorization.
- Preventing CSRF attacks in case you are using cookies to store the JWT.


## Verifying a JWT using a jwt verification library

<AppInfoForm askForAPIDomain>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,12 @@ import {PreBuiltOrCustomUISwitcher, PreBuiltUIContent, CustomUIContent} from "/s
import FrontendPreBuiltUITabs from "/src/components/tabs/FrontendPreBuiltUITabs"
import FrontendCustomUITabs from "/src/components/tabs/FrontendCustomUITabs"
import FrontendMobileSubTabs from "/src/components/tabs/FrontendMobileSubTabs"
import { OAuthVerifyTokensDisclaimer }from "/src/components/OAuthDisclaimer"

# Fetching the access token string

<OAuthVerifyTokensDisclaimer />

## On the backend

<BackendSDKTabs>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ SuperTokens.init({
let response = await original.signUpPOST!(input);
if (response.status === "OK") {
// sign up successful
let actualEmail = input.formFields.find(i => i.id === "actualEmail")!.value;
let actualEmail = input.formFields.find(i => i.id === "actualEmail")!.value as string;
if (actualEmail === "") {
// User did not provide an email.
// This is possible since we set optional: true
Expand Down Expand Up @@ -1008,7 +1008,7 @@ SuperTokens.init({
// ...override from previous code snippet...
// highlight-start
generatePasswordResetTokenPOST: async function (input) {
let emailOrUsername = input.formFields.find(i => i.id === "email")!.value;
let emailOrUsername = input.formFields.find(i => i.id === "email")!.value as string;
if (isInputEmail(emailOrUsername)) {
let userId = await getUserUsingEmail(emailOrUsername);
if (userId !== undefined) {
Expand All @@ -1030,7 +1030,7 @@ SuperTokens.init({
}
}

let username = input.formFields.find(i => i.id === "email")!.value;
let username = input.formFields.find(i => i.id === "email")!.value as string;
let superTokensUsers: supertokensTypes.User[] = await SuperTokens.listUsersByAccountInfo(input.tenantId, {
email: username
});
Expand Down Expand Up @@ -1734,4 +1734,4 @@ When building your custom UI on the frontend, pleas ebe sure to pass the `"actua

</CustomUIContent>

</PreBuiltOrCustomUISwitcher>
</PreBuiltOrCustomUISwitcher>
Loading

0 comments on commit 2ef7a46

Please sign in to comment.