<!-- llms.txt: https://workos.com/llms.txt -->

# Profile

A Profile is an object that represents an authenticated user. The Profile object contains information relevant to a user in the form of normalized attributes.

After receiving the Profile for an authenticated user, use the Profile object attributes to persist relevant data to your application's user model for the specific, authenticated user.

To surface additional attributes on the Profile, refer to the [SSO custom attributes](https://workos.com/docs/sso/attributes/custom-attributes) guide.

## Get a Profile and Token

Get an access token along with the user [Profile](https://workos.com/docs/reference/sso/profile) using the code passed to your [Redirect URI](https://workos.com/docs/reference/sso/get-authorization-url/redirect-uri).

:::code-group

```bash language="curl" title="Request" tab="1"
curl --request POST \
  --url "https://api.workos.com/sso/token" \
  --header "Content-Type: application/json" \
  -d @- <<'BODY'
    {
        "client_id": "client_01HZBC6N1EB1ZY7KG32X",
        "client_secret": "sk_example_123456789",
        "code": "authorization_code_value",
        "grant_type": "authorization_code"
    }
BODY
```

```js language="js" title="Request" tab="1"
import { WorkOS } from '@workos-inc/node';

const workos = new WorkOS('sk_example_123456789');

const { access_token, profile, oauth_tokens } =
  await workos.sso.getProfileAndToken({
    code: '01DMEK0J53CVMC32CK5SE0KZ8Q',
    clientId: 'client_123456789',
  });
```

```rb language="ruby" title="Request" tab="1"
# workos:manual — authorization_code sample; code is conditionally required
require "workos"

WorkOS.configure do |config|
  config.api_key = "sk_example_123456789"
end

WorkOS.client.sso.get_profile_and_token(code: "authorization_code_value")
```

```py language="python" title="Request" tab="1"
# workos:manual — authorization_code sample; code is conditionally required
from workos import WorkOSClient

client = WorkOSClient(api_key="sk_example_123456789", client_id="client_123456789")

client.sso.get_profile_and_token(code="authorization_code_value")
```

```go language="go" title="Request" tab="1"
// workos:manual — authorization_code sample; code is conditionally required
package main

import (
	"context"

	"github.com/workos/workos-go/v10"
)

func main() {
	client := workos.NewClient("sk_example_123456789")

	_, err := client.SSO().GetProfileAndToken(context.Background(), &workos.SSOGetProfileAndTokenParams{
		Code: "authorization_code_value",
	})
	if err != nil {
		panic(err)
	}
}
```

```php language="php" title="Request" tab="1"
<?php
// workos:manual — authorization_code sample; code is conditionally required

use WorkOS\WorkOS;

$workos = new WorkOS(
    apiKey: "sk_example_123456789",
    clientId: "client_123456789",
);

$workos->sso()->getProfileAndToken(code: "authorization_code_value");
```

```java language="java" title="Request" tab="1"
// workos:manual — authorization_code sample; code is conditionally required
import com.workos.WorkOS;
import com.workos.sso.SSOApi.GetProfileAndTokenOptions;

WorkOS workos = new WorkOS("sk_example_123456789");

GetProfileAndTokenOptions options =
    GetProfileAndTokenOptions.builder().code("authorization_code_value").build();

workos.sso.getProfileAndToken(options);
```

```cs language="dotnet" title="Request" tab="1"
// workos:manual — authorization_code sample; code is conditionally required
using WorkOS;

var client = new WorkOSClient(new WorkOSOptions {
    ApiKey = "sk_example_123456789",
    ClientId = "client_123456789",
});

await client.SSO.GetProfileAndTokenAsync(new SSOGetProfileAndTokenOptions {
    Code = "authorization_code_value",
});
```

```rust language="rust" title="Request" tab="1"
// workos:manual — authorization_code sample; code is conditionally required
use workos::Client;
use workos::sso::GetProfileAndTokenParams;

#[tokio::main]
async fn main() -> Result<(), workos::Error> {
    let client = Client::builder()
        .api_key("sk_example_123456789")
        .client_id("client_123456789")
        .build();

    let _result = client
        .sso()
        .get_profile_and_token(
            GetProfileAndTokenParams {
                code: "authorization_code_value".into(),
                ..Default::default()
            }
        )
        .await?;

    Ok(())
}
```

```json language="json" title="Response" tab="2"
{
  "token_type": "Bearer",
  "access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6InNzby...",
  "expires_in": 600,
  "profile": {
    "object": "profile",
    "id": "prof_01DMC79VCBZ0NY2099737PSVF1",
    "organization_id": "org_01EHQMYV6MBK39QC5PZXHY59C3",
    "connection_id": "conn_01E4ZCR3C56J083X43JQXF3JK5",
    "connection_type": "OktaSAML",
    "idp_id": "103456789012345678901",
    "email": "todd@example.com",
    "first_name": "Todd",
    "last_name": "Rundgren",
    "name": "Todd Rundgren",
    "role": {
      "slug": "admin"
    },
    "roles": [
      {
        "slug": "admin"
      }
    ],
    "groups": [
      "Engineering",
      "Admins"
    ],
    "custom_attributes": {},
    "raw_attributes": {}
  }
}
```

:::

## Get a User Profile

Exchange an access token for a user's [Profile](https://workos.com/docs/reference/sso/profile). Because this profile is returned in the [Get a Profile and Token endpoint](https://workos.com/docs/reference/sso/profile/get-profile-and-token) your application usually does not need to call this endpoint. It is available for any authentication flows that require an additional endpoint to retrieve a user's profile.

:::code-group

```bash language="curl" title="Request" tab="1"
curl "https://api.workos.com/sso/profile" \
  --header "Authorization: Bearer 01DMEK0J53CVMC32CK5SE0KZ8Q"
```

```js language="js" title="Request" tab="1"
import { WorkOS } from '@workos-inc/node';

const workos = new WorkOS('sk_example_123456789');

const profile = await workos.sso.getProfile({
  accessToken: '01DMEK0J53CVMC32CK5SE0KZ8Q',
});
```

```rb language="ruby" title="Request" tab="1"
require "workos"

WorkOS.configure do |config|
  config.api_key = "sk_example_123456789"
end

WorkOS.client.sso.get_profile
```

```py language="python" title="Request" tab="1"
from workos import WorkOSClient

client = WorkOSClient(api_key="sk_example_123456789", client_id="client_123456789")

client.sso.get_profile()
```

```go language="go" title="Request" tab="1"
package main

import (
	"context"

	"github.com/workos/workos-go/v10"
)

func main() {
	client := workos.NewClient("sk_example_123456789")

	_, err := client.SSO().GetProfile(context.Background())
	if err != nil {
		panic(err)
	}
}
```

```php language="php" title="Request" tab="1"
<?php

use WorkOS\WorkOS;

$workos = new WorkOS(
    apiKey: "sk_example_123456789",
    clientId: "client_123456789",
);

$workos->sso()->getProfile();
```

```java language="java" title="Request" tab="1"
import com.workos.WorkOS;

WorkOS workos = new WorkOS("sk_example_123456789");

workos.sso.getProfile();
```

```cs language="dotnet" title="Request" tab="1"
using WorkOS;

var client = new WorkOSClient(new WorkOSOptions {
    ApiKey = "sk_example_123456789",
    ClientId = "client_123456789",
});

await client.SSO.GetProfileAsync();
```

```rust language="rust" title="Request" tab="1"
use workos::Client;

#[tokio::main]
async fn main() -> Result<(), workos::Error> {
    let client = Client::builder()
        .api_key("sk_example_123456789")
        .client_id("client_123456789")
        .build();

    let _result = client
        .sso()
        .get_profile()
        .await?;

    Ok(())
}
```

```json language="json" title="Response" tab="2"
{
  "object": "profile",
  "id": "prof_01DMC79VCBZ0NY2099737PSVF1",
  "organization_id": "org_01EHQMYV6MBK39QC5PZXHY59C3",
  "connection_id": "conn_01E4ZCR3C56J083X43JQXF3JK5",
  "connection_type": "OktaSAML",
  "idp_id": "103456789012345678901",
  "email": "todd@example.com",
  "first_name": "Todd",
  "last_name": "Rundgren",
  "name": "Todd Rundgren",
  "role": {
    "slug": "admin"
  },
  "roles": [
    {
      "slug": "admin"
    }
  ],
  "groups": [
    "Engineering",
    "Admins"
  ],
  "custom_attributes": {},
  "raw_attributes": {}
}
```

:::

### profile

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `object` | "profile" | Yes | Distinguishes the Profile object. |
| `id` | string | Yes | Unique identifier for the user, assigned by WorkOS. This value can be persisted to the Developer's user model and used as a unique key for identifying a specific user. |
| `connection_id` | string | Yes | Unique identifier for the Connection to which the Profile belongs. |
| `connection_type` | enum | Yes | connection.connection_type |
| `organization_id` | string | No | Unique identifier for the Organization in which the Connection resides. |
| `email` | string | Yes | The user's email address. |
| `first_name` | string | No | The user's first name. |
| `last_name` | string | No | The user's last name. |
| `name` | string | No | The user's full name. |
| `idp_id` | string | Yes | Unique identifier for the user, assigned by the Identity Provider. Different Identity Providers use different ID formats. One possible use case for idp_id is associating a user's SSO Profile with any relevant Directory Sync actions related to that user. |
| `role` | object | Yes | profile.role |
| `custom_attributes` | object | Yes | Object containing custom attributes that have been mapped from the Identity Provider. These attributes are configured in the [WorkOS Dashboard](https://dashboard.workos.com/) and can include both predefined and custom attributes. For more information about configuring custom attributes, see the [IdP Attributes](/sso/attributes) guide. |

### POST /sso/token

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `subject_token` | string | No | The OIDC ID token to exchange. Required when `grant_type` is `urn:ietf:params:oauth:grant-type:token-exchange`. Must be sent in the request body. |
| `subject_token_type` | "urn:ietf:params:oauth:token-type:id_token" | No | The type of the subject token. Required when `grant_type` is `urn:ietf:params:oauth:grant-type:token-exchange`. Must be sent in the request body. |
| `organization_id` | string | No | The ID of the organization whose connection the subject token is validated against. Required when `grant_type` is `urn:ietf:params:oauth:grant-type:token-exchange`. Must be sent in the request body. |

#### Parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `client_id` | string | Yes | The client ID of the WorkOS environment. |
| `client_secret` | string | Yes | The client secret of the WorkOS environment. |
| `code` | string | No | The authorization value which was passed back as a query parameter in the callback to the [Redirect URI](/reference/sso/get-authorization-url/redirect-uri). |
| `grant_type` | "authorization_code" \| "urn:ietf:params:oauth:grant-type:token-exchange" | Yes | The method by which your application will receive an access token. This value should be `authorization_code`. |

#### Returns

| Field | Type | Description |
| --- | --- | --- |
| `token_type` | "Bearer" | The type of token issued. |
| `access_token` | string | An access token that can be exchanged for a user profile. Access tokens expire 5 minutes after they're created. |
| `expires_in` | integer | The lifetime of the access token in seconds. |
| `profile` | object | The user profile returned by the identity provider. |
| `oauth_tokens` | object | OAuth tokens from the identity provider when using OAuth connections. Contains the provider name, access token, refresh token, expiration time, and scopes. |

### GET /sso/profile

#### Returns

| Field | Type | Description |
| --- | --- | --- |
| `profile` | object | Distinguishes the profile object. |