> ## 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)

> Setup SSO for All-In-One widget for a seamless experience.

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

The All-In-One widget supports authenticating your users via SSO.

Here’s what you need to do:

1. Log in to acquire your private key from SSO settings. Ensure that you store this key securely on your server and prevent unauthorized access.

2. When a user visits the widget, send a request to your server to generate a JWT token.

3. Generate a token on your server with customer data using the provided snippet.

4. Pass the generated JWT token to the Supahub widget for authentication.

## SSO Setup

<Steps>
  <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="Pass the token back to your app and into our widget">
    The token will be used for user authentication.

    <CodeGroup>
      ```javascript HTML theme={null}
      <script id="supahub" type="text/javascript">
        !(function (s, u, p, a) {
          function supahub() {
            var g = u.createElement(p),
              h = u.getElementsByTagName(p)[0];
            (g.id = a),
              (g.src = "https://widget.supahub.com/sdk.js"),
              h.parentNode.insertBefore(g, h);
            g.onload = function () {
              window.SupahubWidget("portal", {
                workspaceName: "workspace-name", // Required: Copy your workspace name from 'workspace-name.supahub.com'
                theme: "light", // Required: Options ("dark" | "light")
                displayType: "popover", // Required: Options ("popover" | "popup")
                position: "right", // Optional: Options ("right" | "left")
                jwtToken: "Generated_JWT_Token", // Optional: Replace with the token generated from your server
              });
            };
          }
          "function" != typeof s.SupahubWidget &&
            (s.SupahubWidget = function () {
              (s.SupahubWidget.q = s.SupahubWidget.q || []).push(arguments);
            }),
            "complete" === u.readyState || "interactive" === u.readyState
              ? supahub()
              : s.addEventListener("DOMContentLoaded", supahub);
        })(window, document, "script", "supahub-sdk");
      </script>
      ```

      ```javascript Next.js theme={null}
      "use client"; // NextJS 13 requires this. Remove if you are using NextJS 12 or lower.

      import Script from "next/script";

      const AllInOneWidget = () => {
        return (
          <>
            <Script id="supahub" strategy="afterInteractive" type="text/javascript">
              {`!(function (s, u, p, a) {
                function supahub() {var g=u.createElement(p),h=u.getElementsByTagName(p)[0];(g.id=a),(g.src="https://widget.supahub.com/sdk.js"),h.parentNode.insertBefore(g, h);
                  g.onload = function () {
                    window.SupahubWidget("portal", {
                      workspaceName: "workspace-name", // Required: Copy your workspace name from 'workspace-name.supahub.com'
                      theme: "light", // Required: Options ("dark" | "light")
                      displayType: "popover", // Required: Options ("popover" | "popup")
                      position: "right", // Optional: Options ("right" | "left")
                      jwtToken: "Generated_JWT_Token", // Optional: Replace with the token generated from your server
                    });
                  }};
                "function"!=typeof s.SupahubWidget&&(s.SupahubWidget=function(){(s.SupahubWidget.q=s.SupahubWidget.q||[]).push(arguments);}),"complete"===u.readyState||"interactive"===u.readyState?supahub():s.addEventListener("DOMContentLoaded", supahub);
                })(window, document, "script", "supahub-sdk");`}
            </Script>
          </>
        );
      };

      export default AllInOneWidget;
      ```

      ```javascript Vue.js theme={null}
      <script lang="ts" setup>
      import { onMounted } from "vue";

      onMounted(() => {
        if (document.getElementById("supahub-sdk")) {
          return;
        }

        const script = document.createElement("script");
        script.id = "supahub-sdk";
        script.src = "https://widget.supahub.com/sdk.js";
        script.async = true;
        script.onload = () => {
          const win: any = window;
          win.SupahubWidget("portal", {
            workspaceName: "workspace-name", // Required: Copy your workspace name from 'workspace-name.supahub.com'
            theme: "light", // Required: Options ("dark" | "light")
            displayType: "popover", // Required: Options ("popover" | "popup")
            position: "right", // Optional: Options ("right" | "left")
            jwtToken: "Generated_JWT_Token", // Optional: Replace with the token generated from your server
          });
        };

        document.head.appendChild(script);
      });
      </script>

      <template>
        <h1>This is a component</h1>
      </template>

      <style>
      ...
      </style>
      ```
    </CodeGroup>
  </Step>
</Steps>
