> ## Documentation Index
> Fetch the complete documentation index at: https://docs.supahub.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Single Sign-On (SSO)

> Enable seamless access to Supahub's public hub by integrating Single Sign-On (SSO) with your app's existing authentication credentials.

<Tip>Growth or above plan is required.</Tip>

The Single Sign-On (SSO) feature allows your users to authenticate once and gain access to your feedback hub seamlessly. With SSO integration, you can enable your users to log in to Supahub using their existing credentials from your authentication system. This developer documentation will guide you through the steps to integrate SSO with Supahub.

## Prerequisites

Before you begin, make sure you have:

1. Administrative access to your Supahub account.
2. Growth plan and above.
3. Access to your Private Key from SSO settings.

## How it works

Here is a summary of the authentication flow:

1. The user wants to authenticate and clicks on the "Login with YourWorkspaceName" button on your public hub's navbar.
2. They are redirected to your website's custom login page, with the `redirectTo` parameter appended to the URL: `https://yourdomain.com/sso/supahub?redirectTo=https://workspace-name.supahub.com/changelog`
3. Once the user is authenticated, your authentication system generates a JWT token.
4. The user is then redirected back to Supahub along with the generated token and the original `redirectTo` parameter passed along: `https://workspace-name.supahub.com/api/auth/sso?jwt=payload&redirectTo=https://workspace-name.supahub.com/changelog`
5. Supahub receives the token and logs the user into the system using the validated token.
6. Finally, Supahub automatically redirects the user back to the page on your public hub where they initially clicked on the "Login with YourWorkspaceName" button.

## Steps to Integrate SSO with Supahub

<Steps>
  <Step title="Set up a dedicated SSO page">
    Create a page on your website that will handle the authentication process. For example, you can use the URL: `https://yourdomain.com/sso/supahub`. Alternatively, you can use your existing authentication page (login/signup). This page will receive and process authentication requests from Supahub.

    Go to your Supahub Dashboard and navigate to the "Settings" section. Look for the SSO settings and enter the URL of the SSO page you created in the "**SSO Redirect URL**" field.

    Once saved the "Login with YourWorkspaceName" button on your public hub's navbar will be shown automatically.
  </Step>

  <Step title="Authenticate Users">
    When a user visits your SSO page, use your app's authentication system to
    authenticate them. This could involve verifying their credentials or any other
    authentication mechanism you have in place.
  </Step>

  <Step title="Install JWT packages">
    Install the required packages for JWT token generation on your server.

    <CodeGroup>
      ```javascript Node.js theme={null}
      npm install --save jsonwebtoken
      ```

      ```python Python theme={null}
      pip install pyjwt
      ```

      ```javascript C# theme={null}
      // Instructions here
      https://www.nuget.org/packages/System.IdentityModel.Tokens.Jwt/
      ```

      ```java Java theme={null}
      // Instructions here
      https://github.com/jwtk/jjwt#install
      ```

      ```go Go theme={null}
      go get github.com/golang-jwt/jwt
      ```

      ```php PHP theme={null}
      composer require firebase/php-jwt
      ```
    </CodeGroup>
  </Step>

  <Step title="Generate the JWT token">
    Copy and use the “Private Key” from SSO settings to generate a JWT token on your server.

    <CodeGroup>
      ```javascript Node.js theme={null}
      var jwt = require("jsonwebtoken");
      const SSO_KEY = "YOUR_PRIVATE_SSO_KEY";

      function generateJWTToken(user) {
          var userData = {
              email: user.email, // Required
              name: user.name, // Required
              id: user.id, // Required
          };

          // The userData object can include any additional details you wish to provide about a user to Supahub. Ensure to follow the same format shown in the Supahub.identify method, as outlined at https://docs.supahub.com/identify/user

          return jwt.sign(userData, SSO_KEY, {
              algorithm: "HS256",
          });
      }
      ```

      ```python Python theme={null}
      import jwt
      from datetime import datetime, timedelta

      SSO_KEY = "YOUR_PRIVATE_SSO_KEY"

      def generate_JWT_token(user):
          userData = {
              'email': user['email'], # Required
              'name': user['name'], # Required
              'id': user['id'], # Required
          }

          # The userData object can include any additional details you wish to provide about a user to Supahub. Ensure to follow the same format shown in the Supahub.identify method, as outlined at https://docs.supahub.com/identify/user

          return jwt.encode(userData, SSO_KEY, algorithm='HS256')
      ```

      ```javascript C# theme={null}
      using System;
      using System.IdentityModel.Tokens.Jwt;
      using System.Security.Claims;
      using Microsoft.IdentityModel.Tokens;

      public string GenerateJwtToken(User user)
      {
          var claims = new[]
          {
              new Claim("email", user.email), // Required
              new Claim("name", user.name), // Required
              new Claim("id", user.id), // Required
          };

          // The userData object can include any additional details you wish to provide about a user to Supahub. Ensure to follow the same format shown in the Supahub.identify method, as outlined at https://docs.supahub.com/identify/user

          var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("YOUR_PRIVATE_SSO_KEY"));
          var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

          var token = new JwtSecurityToken(
              claims: claims,
              signingCredentials: creds);

          return new JwtSecurityTokenHandler().WriteToken(token);
      }
      ```

      ```java Java theme={null}
      import io.jsonwebtoken.Jwts;
      import io.jsonwebtoken.SignatureAlgorithm;

      String SSO_KEY = "YOUR_PRIVATE_SSO_KEY";

      public String generateJwtToken(User user) {
          Map<String, Object> claims = new HashMap<>();
          claims.put("email", user.getEmail()); // Required
          claims.put("name", user.getName()); // Required
          claims.put("id", user.getId()); // Required

          // The userData object can include any additional details you wish to provide about a user to Supahub. Ensure to follow the same format shown in the Supahub.identify method, as outlined at https://docs.supahub.com/identify/user

          return Jwts.builder()
              .setClaims(claims)
              .signWith(SignatureAlgorithm.HS256, SSO_KEY)
              .compact();
      }
      ```

      ```go Go theme={null}
      import (
          "github.com/golang-jwt/jwt",
      )

      var SSO_KEY = []byte("YOUR_PRIVATE_SSO_KEY")

      func GenerateJwtToken(user User) (string, error) {
          token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
              "email": user.email, // Required
              "name": user.name, // Required
              "id": user.id, // Required
          })

          // The userData object can include any additional details you wish to provide about a user to Supahub. Ensure to follow the same format shown in the Supahub.identify method, as outlined at https://docs.supahub.com/identify/user

          return token.SignedString([]byte(PrivateKey));
      }
      ```

      ```php PHP theme={null}
      use FirebaseJWTJWT;

      $SSO_KEY = "YOUR_PRIVATE_SSO_KEY";

      function generateJwtToken($user) {
          $payload = array(
              "email" => $user['email'], // Required
              "name" => $user['name'], // Required
              "id" => $user['id'], // Required
          );

          // The userData object can include any additional details you wish to provide about a user to Supahub. Ensure to follow the same format shown in the Supahub.identify method, as outlined at https://docs.supahub.com/identify/user

          return JWT::encode($payload, $SSO_KEY);
      }
      ```
    </CodeGroup>

    <Warning>
      Private Key should be kept secure and not to be shared. Add it in your .env
      file.
    </Warning>

    <Note>
      To enhance security measures, Single Sign-On (SSO) tokens are restricted from authenticating users with administrative privileges within any Supahub workspace. Instead, these users will need to log in using the dedicated portal at workspace.supahub.com
    </Note>
  </Step>

  <Step title="Redirect the user back to Supahub">
    Redirect the user to the Supahub JWT endpoint with the `jwt` and `redirectTo` URL.
    `https://workspace-name.supahub.com/api/auth/sso?jwt=payload&redirectTo=https://workspace-name.supahub.com/changelog`

    <Warning>
      Note: If you have custom domain implemented, the redirect URL will be:
      `https://feedback.yourdomain.com/api/auth/sso?jwt=payload&redirectTo=https://feedback.yourdomain.com/changelog`
    </Warning>
  </Step>
</Steps>

## Add User & Company Data

You can also pass the user and company data inside JWT token generation.

```javascript Node.js theme={null}
var jwt = require("jsonwebtoken");
const SSO_KEY = "YOUR_PRIVATE_SSO_KEY";

function generateJWTToken(user) {
  var userData = {
    email: user.email, // Required
    name: user.name, // Required

    id: "786", // Required: Unique id that you are using to identify your user

    avatar: "https://example.com/images/user-profile.jpg", // Optional

    customFields: {
      title: "Product Manager",
      location: "Paris",
    }, // Optional: Add any type of field, in the format ({key1: "value1", key2: "value2"})

    // Company Data
    companies: [
      {
        id: "786", // Required
        name: "Acme Inc.", // Required
        logo: "https://example.com/images/company-logo.jpg", // Optional
        monthlySpend: 300, // Optional, but recommended
        createdAt: "2023-05-19T15:35:49.915Z", // Optional
      },
    ],
  };

  return jwt.sign(userData, SSO_KEY, {
    algorithm: "HS256",
  });
}
```

## Restricting end-users' access

By combining private workspace settings with Single Sign-On (SSO), you can create a secure environment for your users. Follow the below steps:

<Steps>
  <Step title="Private Workspace Configuration">
    Enable private workspace settings to restrict public access. Go to Settings > General > Make Workspace Private.
  </Step>

  <Step title="Authenticate Users">
    Access through [configured SSO integration](#steps-to-integrate-sso-with-supahub) ensures only verified users can
    submit and view feedback hub.
  </Step>
</Steps>
