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

# Partner SSO

> Enable partners to provide single sign-on (SSO) access to their customers through their own SaaS portal using JWT-based authentication.

#### Partner

A Partner is an MSSP (Managed Security Service Provider) that manages multiple customers inside Plerion. Partners have the option to create any number of tenants within their Plerion Organization.

#### Partner SSO

**Partner SSO** is a single sign-on feature that allows Partners to authorize their customers to access their Plerion Tenant through their own SaaS portal, eliminating the need for a separate sign-up process.

**Key points:**

* *Partner SSO* uses JWT based authentication (Refer to [JWT Payload and Signature](#jwt-payload-and-signature) for payload format)
* *Partner SSO* only allows access at tenant level. i.e. Users can be granted only two levels of access **Tenant Admin** and **Tenant Read-only**
* Only **Organization Admin** can set the [public-key](#uploading-the-public-key) needed to enable Partner SSO
* Currently, only tokens signed with `RS256` algorithm are supported
* Existing users (who are not authenticated using Partner SSO) can't sign in using Partner SSO
  * To enable existing user to sign in via Partner SSO refer to [onboarding existing user](#onboarding-existing-user)
* Partner SSO users have access to only a single tenant
  * If you wish to change the tenant associated with the user, you can delete the user and have them sign in again with a new tenant. Refer to [onboarding existing user](#onboarding-existing-user)
* Roles for Partner SSO users can be changed by passing a different role in the JWT Payload

## Implementing partner SSO

### Uploading the public key

To upload the public key you need to have **Organization Admin** access. You can then upload the associated public key by navigating to `Settings` > `Partner single sign-on` and clicking on `Add Public Key`.

<Frame>
  <img src="https://mintcdn.com/pleriondocs/rUKExsSzIxUC775q/images/administration/add-partner-sso-public-key.png?fit=max&auto=format&n=rUKExsSzIxUC775q&q=85&s=48a98843977951413dd9272d95c30533" alt="Add Public Key" width="1912" height="674" data-path="images/administration/add-partner-sso-public-key.png" />
</Frame>

Make sure to copy and paste the entire public key string, which typically starts with *'-----BEGIN PUBLIC KEY-----'* and ends with *'-----END PUBLIC KEY-----'*.

### JWT payload and signature

The JWT payload should contain following properties:

```ts theme={"system"}
    {
      "organizationId" : "<organization_id>",
      "tenantId" : "<tenant_id>",
      "role" : 'admin' | 'readOnly',
      "email" : "<user_email_>",
      "exp": <token_expiration_time>
      "name" : "<name_of_user>"
    }
```

* `organizationId`<span style={{ type:"mdxJsxAttributeValueExpression",value:"{color:'#FF0000'}",data:{estree:{type:"Program",start:2501,end:2518,body:[{type:"ExpressionStatement",expression:{type:"ObjectExpression",start:2501,end:2518,loc:{start:{line:47,column:31,offset:2501},end:{line:47,column:48,offset:2518}},properties:[{type:"Property",start:2502,end:2517,loc:{start:{line:47,column:32,offset:2502},end:{line:47,column:47,offset:2517}},method:false,shorthand:false,computed:false,key:{type:"Identifier",start:2502,end:2507,loc:{start:{line:47,column:32,offset:2502},end:{line:47,column:37,offset:2507}},name:"color",range:[2502,2507]},value:{type:"Literal",start:2508,end:2517,loc:{start:{line:47,column:38,offset:2508},end:{line:47,column:47,offset:2517}},value:"#FF0000",raw:"'#FF0000'",range:[2508,2517]},kind:"init",range:[2502,2517]}],range:[2501,2518]},start:2501,end:2518,loc:{start:{line:47,column:31,offset:2501},end:{line:47,column:48,offset:2518}},range:[2501,2518]}],sourceType:"module",comments:[],loc:{start:{line:47,column:31,offset:2501},end:{line:47,column:48,offset:2518}},range:[2501,2518]}} }}>
  \*</span>

  : The ID of the Plerion Organization
* `tenantId`<span style={{ type:"mdxJsxAttributeValueExpression",value:"{color:'#FF0000'}",data:{estree:{type:"Program",start:2591,end:2608,body:[{type:"ExpressionStatement",expression:{type:"ObjectExpression",start:2591,end:2608,loc:{start:{line:48,column:25,offset:2591},end:{line:48,column:42,offset:2608}},properties:[{type:"Property",start:2592,end:2607,loc:{start:{line:48,column:26,offset:2592},end:{line:48,column:41,offset:2607}},method:false,shorthand:false,computed:false,key:{type:"Identifier",start:2592,end:2597,loc:{start:{line:48,column:26,offset:2592},end:{line:48,column:31,offset:2597}},name:"color",range:[2592,2597]},value:{type:"Literal",start:2598,end:2607,loc:{start:{line:48,column:32,offset:2598},end:{line:48,column:41,offset:2607}},value:"#FF0000",raw:"'#FF0000'",range:[2598,2607]},kind:"init",range:[2592,2607]}],range:[2591,2608]},start:2591,end:2608,loc:{start:{line:48,column:25,offset:2591},end:{line:48,column:42,offset:2608}},range:[2591,2608]}],sourceType:"module",comments:[],loc:{start:{line:48,column:25,offset:2591},end:{line:48,column:42,offset:2608}},range:[2591,2608]}} }}>
  \*</span>

  : The ID of Plerion Tenant. Once a user is bound to a `tenantId`, it cannot be updated.
* `role`<span style={{ type:"mdxJsxAttributeValueExpression",value:"{color:'#FF0000'}",data:{estree:{type:"Program",start:2728,end:2745,body:[{type:"ExpressionStatement",expression:{type:"ObjectExpression",start:2728,end:2745,loc:{start:{line:49,column:21,offset:2728},end:{line:49,column:38,offset:2745}},properties:[{type:"Property",start:2729,end:2744,loc:{start:{line:49,column:22,offset:2729},end:{line:49,column:37,offset:2744}},method:false,shorthand:false,computed:false,key:{type:"Identifier",start:2729,end:2734,loc:{start:{line:49,column:22,offset:2729},end:{line:49,column:27,offset:2734}},name:"color",range:[2729,2734]},value:{type:"Literal",start:2735,end:2744,loc:{start:{line:49,column:28,offset:2735},end:{line:49,column:37,offset:2744}},value:"#FF0000",raw:"'#FF0000'",range:[2735,2744]},kind:"init",range:[2729,2744]}],range:[2728,2745]},start:2728,end:2745,loc:{start:{line:49,column:21,offset:2728},end:{line:49,column:38,offset:2745}},range:[2728,2745]}],sourceType:"module",comments:[],loc:{start:{line:49,column:21,offset:2728},end:{line:49,column:38,offset:2745}},range:[2728,2745]}} }}>
  \*</span>

  : Role to assign to user. Can only be `admin` or `readOnly`. User roles can be updated by passing different role in the parameter
* `email`<span style={{ type:"mdxJsxAttributeValueExpression",value:"{color:'#FF0000'}",data:{estree:{type:"Program",start:2909,end:2926,body:[{type:"ExpressionStatement",expression:{type:"ObjectExpression",start:2909,end:2926,loc:{start:{line:50,column:22,offset:2909},end:{line:50,column:39,offset:2926}},properties:[{type:"Property",start:2910,end:2925,loc:{start:{line:50,column:23,offset:2910},end:{line:50,column:38,offset:2925}},method:false,shorthand:false,computed:false,key:{type:"Identifier",start:2910,end:2915,loc:{start:{line:50,column:23,offset:2910},end:{line:50,column:28,offset:2915}},name:"color",range:[2910,2915]},value:{type:"Literal",start:2916,end:2925,loc:{start:{line:50,column:29,offset:2916},end:{line:50,column:38,offset:2925}},value:"#FF0000",raw:"'#FF0000'",range:[2916,2925]},kind:"init",range:[2910,2925]}],range:[2909,2926]},start:2909,end:2926,loc:{start:{line:50,column:22,offset:2909},end:{line:50,column:39,offset:2926}},range:[2909,2926]}],sourceType:"module",comments:[],loc:{start:{line:50,column:22,offset:2909},end:{line:50,column:39,offset:2926}},range:[2909,2926]}} }}>
  \*</span>

  : Email of the user. Each user needs to have a unique email address.
* `exp`<span style={{ type:"mdxJsxAttributeValueExpression",value:"{color:'#FF0000'}",data:{estree:{type:"Program",start:3026,end:3043,body:[{type:"ExpressionStatement",expression:{type:"ObjectExpression",start:3026,end:3043,loc:{start:{line:51,column:20,offset:3026},end:{line:51,column:37,offset:3043}},properties:[{type:"Property",start:3027,end:3042,loc:{start:{line:51,column:21,offset:3027},end:{line:51,column:36,offset:3042}},method:false,shorthand:false,computed:false,key:{type:"Identifier",start:3027,end:3032,loc:{start:{line:51,column:21,offset:3027},end:{line:51,column:26,offset:3032}},name:"color",range:[3027,3032]},value:{type:"Literal",start:3033,end:3042,loc:{start:{line:51,column:27,offset:3033},end:{line:51,column:36,offset:3042}},value:"#FF0000",raw:"'#FF0000'",range:[3033,3042]},kind:"init",range:[3027,3042]}],range:[3026,3043]},start:3026,end:3043,loc:{start:{line:51,column:20,offset:3026},end:{line:51,column:37,offset:3043}},range:[3026,3043]}],sourceType:"module",comments:[],loc:{start:{line:51,column:20,offset:3026},end:{line:51,column:37,offset:3043}},range:[3026,3043]}} }}>
  \*</span>

  : A JSON numeric value representing the number of seconds from epoch (1970-01-01T00:00:00Z UTC). Refer to [RFC7519#Section-4.1.4](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.4) for more information.
* `name` : Name of the user

*Fields marked as `*` are required.*

To find the details of the organization like organizationId and tenant Id, navigate to `Settings` > `Overview` and get the values.

You should sign the JWT token with the `RS256` private-key associated with the public-key uploaded in the [Plerion Platform](#uploading-the-public-key).

### Endpoint for authentication

You can submit a form to the following endpoint by including the `token` parameter, with the value being the JWT token.

```
POST https://au.app.plerion.com/api/base/auth/partner-sso/login
```

**Headers:**

```
Content-Type: application/x-www-form-urlencoded
```

**Parameters:**

```ts application/x-www-form-urlencoded theme={"system"}
   token=<signed_jwt>
```

Please provide the signed JWT in the `token` property in the body.

**Response:**

*Status Code*

`302`

*Headers:*

`Location: <redirect_url>`

#### Login flow

Illustrated below is the basic login flow when user tries to sign in via Partner SSO.

<Frame>
  <img src="https://mintcdn.com/pleriondocs/rUKExsSzIxUC775q/images/administration/login-flow.png?fit=max&auto=format&n=rUKExsSzIxUC775q&q=85&s=41c7e20eab3a2d8f072dda6d389edf09" alt="Login Flow" width="1842" height="959" data-path="images/administration/login-flow.png" />
</Frame>

### Onboarding existing user

If a user already has a non-Partner SSO account in Plerion, they cannot sign in as a Partner SSO user.
To allow them to sign in as Partner SSO user, you can delete the existing account and follow the normal Partner SSO sign-in process.

Also, if you wish to change the tenant associated with an existing Partner SSO user, you need to delete the user and follow the normal Partner SSO sign-in process with the new `tenantId`.

##### Check if a user is Partner SSO user

* Navigate to `Admin` > `Users`
* Search for the user and click on the user to open their profile
* Check the `Partner SSO` field

<Frame>
  <img src="https://mintcdn.com/pleriondocs/rUKExsSzIxUC775q/images/administration/partner-sso-user.png?fit=max&auto=format&n=rUKExsSzIxUC775q&q=85&s=d973e0f9df3304a3437c77d7c607fc1f" alt="PartnerSSO User" width="1441" height="723" data-path="images/administration/partner-sso-user.png" />
</Frame>

##### Delete a user:

* Navigate to `Admin` > `Users`
* Click on the action button and select Delete User.

<Frame>
  <img src="https://mintcdn.com/pleriondocs/rUKExsSzIxUC775q/images/administration/user-list-delete.png?fit=max&auto=format&n=rUKExsSzIxUC775q&q=85&s=8af70f73d4443df9dc48e39342d0be22" alt="User List Delete" width="1439" height="722" data-path="images/administration/user-list-delete.png" />
</Frame>

* OR, you can open the user profile by clicking on the user and clicking on the delete button

<Frame>
  <img src="https://mintcdn.com/pleriondocs/rUKExsSzIxUC775q/images/administration/user-view-delete.png?fit=max&auto=format&n=rUKExsSzIxUC775q&q=85&s=14ecf589e5a8e84ab39ba42666d90a4a" alt="User View Delete" width="1437" height="721" data-path="images/administration/user-view-delete.png" />
</Frame>

<br />

**Note**:

* After a user has been deleted, they can sign in using the normal Partner SSO login flow.
* Only Organization Admin can delete users.

### Possible errors

**Body:**

```ts application/json theme={"system"}
    {
      "errors": [
        {
          "code": "<error_code>"
          "message": "<error_message>"
        }
      ]
    }
```

<Tabs>
  <Tab title="401">
    | Code               | Message                                             |
    | :----------------- | :-------------------------------------------------- |
    | InvalidToken       | The provided token is invalid.                      |
    | InvalidPayload     | Relevant message regarding the payload              |
    | InvalidKeyOrTenant | Public Key not set for Tenant or Invalid `tenantId` |
    | ExpiredToken       | The token has expired                               |
  </Tab>

  <Tab title="403">
    | Code                | Message                                               |
    | :------------------ | :---------------------------------------------------- |
    | InactiveUser        | User is disabled in the platform                      |
    | UnauthorizedUser    | User is not a PartnerSSO user                         |
    | InvalidOrganization | The `organizationId` provided in the token is invalid |
    | InvalidTenant       | The `tenantId` provided in the token is invalid       |
  </Tab>
</Tabs>
