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

# Multi-Factor Authentication

# Multi-Factor Authentication

Enroll users in multi-factor authentication for an additional layer of security. MFA can be enabled via the [Authentication page](https://dashboard.workos.com/environment/authentication/features) in the WorkOS dashboard.

## Authentication challenge

Represents a challenge of an authentication factor.

:::code-group{title="Authentication challenge"}

```json language="curl"
{
  "object": "authentication_challenge",
  "id": "auth_challenge_01FVYZWQTZQ5VB6BC5MPG2EYC5",
  "created_at": "2022-02-15T15:26:53.274Z",
  "updated_at": "2022-02-15T15:26:53.274Z",
  "expires_at": "2022-02-15T15:36:53.279Z",
  "authentication_factor_id": "auth_factor_01FVYZ5QM8N98T9ME5BCB2BBMJ"
}
```

```js language="js"
const challenge = {
  object: 'authentication_challenge',
  id: 'auth_challenge_01FVYZWQTZQ5VB6BC5MPG2EYC5',
  createdAt: '2022-02-15T15:26:53.274Z',
  updatedAt: '2022-02-15T15:26:53.274Z',
  expiresAt: '2022-02-15T15:36:53.279Z',
  authenticationFactorId: 'auth_factor_01FVYZ5QM8N98T9ME5BCB2BBMJ',
};
```

```rb language="ruby"
WorkOS::Challenge.new <<~JSON
  {
    "object": "authentication_challenge",
    "id": "auth_challenge_01FVYZWQTZQ5VB6BC5MPG2EYC5",
    "created_at": "2022-02-15T15:26:53.274Z",
    "updated_at": "2022-02-15T15:26:53.274Z",
    "expires_at": "2022-02-15T15:36:53.279Z",
    "authentication_factor_id": "auth_factor_01FVYZ5QM8N98T9ME5BCB2BBMJ"
  }
JSON
```

```py language="python"
from workos.types.mfa import AuthenticationChallenge

authentication_challenge = AuthenticationChallenge(
    object="authentication_challenge",
    id="auth_challenge_01FVYZWQTZQ5VB6BC5MPG2EYC5",
    created_at="2022-02-15T15:26:53.274Z",
    updated_at="2022-02-15T15:26:53.274Z",
    expires_at="2022-02-15T15:36:53.279Z",
    authentication_factor_id="auth_factor_01FVYZ5QM8N98T9ME5BCB2BBMJ",
)
```

```go language="go"
package main

import (
	"github.com/workos/workos-go/v2/pkg/mfa"
)

func main() {
	challenge := mfa.Challenge{
		ID:        "auth_challenge_01FVYZWQTZQ5VB6BC5MPG2EYC5",
		Object:    "authentication_challenge",
		CreatedAt: "2022-02-15T15:26:53.274Z",
		UpdatedAt: "2022-02-15T15:26:53.274Z",
		ExpiresAt: "2022-02-15T15:36:53.279Z",
		FactorId:  "auth_factor_01FVYZ5QM8N98T9ME5BCB2BBMJ",
	}
}
```

```php language="php"
<?php

$authenticationChallenge = [
    "object" => "authentication_challenge",
    "id" => "auth_challenge_01FVYZWQTZQ5VB6BC5MPG2EYC5",
    "created_at" => "2022-02-15T15:26:53.274Z",
    "updated_at" => "2022-02-15T15:26:53.274Z",
    "expires_at" => "2022-02-15T15:36:53.279Z",
    "authentication_factor_id" => "auth_factor_01FVYZ5QM8N98T9ME5BCB2BBMJ",
];
```

```java language="java"
import com.workos.usermanagement.models.AuthenticationChallenge;

AuthenticationChallenge challenge =
    new AuthenticationChallenge("auth_challenge_01FVYZWQTZQ5VB6BC5MPG2EYC5",
        "2022-02-15T15:26:53.274Z",
        "2022-02-15T15:26:53.274Z",
        "2022-02-15T15:36:53.279Z",
        "auth_factor_01FVYZ5QM8N98T9ME5BCB2BBMJ");
```

:::

## Authentication factor

Represents an authentication factor.

:::code-group{title="Authentication factor"}

```json language="curl"
{
  "object": "authentication_factor",
  "id": "auth_factor_01FVYZ5QM8N98T9ME5BCB2BBMJ",
  "created_at": "2022-02-15T15:14:19.392Z",
  "updated_at": "2022-02-15T15:14:19.392Z",
  "type": "totp",
  "totp": {
    "issuer": "Foo Corp",
    "user": "alan.turing@example.com",
    "qr_code": "data:image/png;base64,{base64EncodedPng}",
    "secret": "NAGCCFS3EYRB422HNAKAKY3XDUORMSRF",
    "uri": "otpauth://totp/FooCorp:alan.turing@example.com?secret=NAGCCFS3EYRB422HNAKAKY3XDUORMSRF&issuer=FooCorp"
  },
  "userId": "user_01FVYZ5QM8N98T9ME5BCB2BBMJ"
}
```

```js language="js"
const factor = {
  object: 'authentication_factor',
  id: 'auth_factor_01FVYZ5QM8N98T9ME5BCB2BBMJ',
  createdAt: '2022-02-15T15:14:19.392Z',
  updatedAt: '2022-02-15T15:14:19.392Z',
  type: 'totp',
  totp: {
    issuer: 'Foo Corp',
    user: 'alan.turing@example.com',
    qrCode: 'data:image/png;base64,{base64EncodedPng}',
    secret: 'NAGCCFS3EYRB422HNAKAKY3XDUORMSRF',
    uri: 'otpauth://totp/FooCorp:alan.turing@example.com?secret=NAGCCFS3EYRB422HNAKAKY3XDUORMSRF&issuer=FooCorp',
  },
  userId: 'user_01FVYZ5QM8N98T9ME5BCB2BBMJ',
};
```

```rb language="ruby"
WorkOS::Factor.new <<~JSON
  {
    "object": "authentication_factor",
    "id": "auth_factor_01FVYZ5QM8N98T9ME5BCB2BBMJ",
    "created_at": "2022-02-15T15:14:19.392Z",
    "updated_at": "2022-02-15T15:14:19.392Z",
    "type": "totp",
    "totp": {
      "issuer": "Foo Corp",
      "user": "alan.turing@example.com",
      "qr_code": "data:image/png;base64,{base64EncodedPng}",
      "secret": "NAGCCFS3EYRB422HNAKAKY3XDUORMSRF",
      "uri": "otpauth://totp/FooCorp:alan.turing@example.com?secret=NAGCCFS3EYRB422HNAKAKY3XDUORMSRF&issuer=FooCorp"
    }
    "user_id": "user_01FVYZ5QM8N98T9ME5BCB2BBMJ"
  }
JSON
```

```py language="python"
from workos.types.mfa import AuthenticationFactorTotpExtended, ExtendedTotpFactor

authentication_factor_totp = AuthenticationFactorTotpExtended(
    object="authentication_factor",
    id="auth_factor_123",
    created_at="2022-02-15T15:14:19.392Z",
    updated_at="2022-02-15T15:14:19.392Z",
    type="totp",
    totp=ExtendedTotpFactor(
        issuer="WorkOS",
        user="alan.turing@example.com",
        qr_code="data:image/png;base64,{base64EncodedPng}",
        secret="NAGCCFS3EYRB422HNAKAKY3XDUORMSRF",
        uri="otpauth://totp/FooCorp:alan.turing@example.com?secret=NAGCCFS3EYRB422HNAKAKY3XDUORMSRF&issuer=FooCorp",
    ),
    user_id="user_123",
)
```

```go language="go"
package main

import (
	"github.com/workos/workos-go/v3/pkg/mfa"
)

func main() {
	enroll := mfa.Factor{
		ID:        "auth_factor_01FVYZ5QM8N98T9ME5BCB2BBMJ",
		CreatedAt: "2022-02-15T15:14:19.392Z",
		UpdatedAt: "2022-02-15T15:14:19.392Z",
		Type:      "totp",
		TOTP: mfa.TOTPDetails{
			QRCode: "data:image/png;base64,{base64EncodedPng}",
			Secret: "NAGCCFS3EYRB422HNAKAKY3XDUORMSRF",
			URI:    "otpauth://totp/FooCorp:alan.turing@example.com?secret=NAGCCFS3EYRB422HNAKAKY3XDUORMSRF&issuer=FooCorp",
		},
	}
}
```

```php language="php"
<?php

$authenticationFactor = [
    "object" => "authentication_factor",
    "id" => "auth_factor_01FVYZ5QM8N98T9ME5BCB2BBMJ",
    "created_at" => "2022-02-15T15:14:19.392Z",
    "updated_at" => "2022-02-15T15:14:19.392Z",
    "type" => "totp",
    "totp" => [
        "issuer" => "Foo Corp",
        "user" => "alan.turing@example.com",
        "qr_code" => "data:image/png;base64,{base64EncodedPng}",
        "secret" => "NAGCCFS3EYRB422HNAKAKY3XDUORMSRF",
        "uri" =>
            "otpauth://totp/FooCorp:alan.turing@example.com?secret=NAGCCFS3EYRB422HNAKAKY3XDUORMSRF&issuer=FooCorp",
    ],
    "user_id" > "user_01FVYZ5QM8N98T9ME5BCB2BBMJ",
];
```

```java language="java"
import com.workos.usermanagement.models.AuthenticationFactor;
import com.workos.usermanagement.models.AuthenticationTotp;

AuthenticationFactor challenge = new AuthenticationFactor(
    "auth_factor_01FVYZ5QM8N98T9ME5BCB2BBMJ",
    "2022-02-15T15:14:19.392Z",
    "2022-02-15T15:14:19.392Z",
    "totp",
    new AuthenticationTotp("Foo Corp",
        "alan.turing@example.com",
        "data:image/png;base64,{base64EncodedPng}",
        "NAGCCFS3EYRB422HNAKAKY3XDUORMSRF",
        "otpauth://totp/FooCorp:alan.turing@example.com?secret=NAGCCFS3EYRB422HNAKAKY3XDUORMSRF&issuer=FooCorp"),
    "user_01FVYZ5QM8N98T9ME5BCB2BBMJ");
```

:::

## Enroll an authentication factor

Enrolls a user in a new [authentication factor](https://workos.com/docs/reference/authkit/mfa/authentication-factor).

:::code-group{title="Request"}

```bash language="curl"
curl --request POST \
  --url https://api.workos.com/user_management/users/user_01E4ZCR3C56J083X43JQXF3JK5/auth_factors \
  --header "Authorization: Bearer sk_example_123456789" \
  --header "Content-Type: application/json" \
  -d @- <<BODY
  {
    "type": "totp",
    "totp_issuer": "Foo Corp",
    "totp_user": "bob@example.com"
  }
BODY
```

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

const workos = new WorkOS('sk_example_123456789');

const { authenticationFactor, authenticationChallenge } =
  await workos.userManagement.enrollAuthFactor({
    userId: 'user_01E4ZCR3C56J083X43JQXF3JK5',
    type: 'totp',
    totpIssuer: 'WorkOS',
    totpUser: 'bob@example.com',
  });
```

```rb language="ruby"
require "workos"

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

WorkOS.client.multi_factor_auth.create_user_auth_factor(
  userland_user_id: "user_01E4ZCR3C56J083X43JQXF3JK5",
  type: "totp"
)
```

```py language="python"
from workos import WorkOSClient

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

client.multi_factor_auth.create_user_auth_factor(
    userland_user_id="user_01E4ZCR3C56J083X43JQXF3JK5", type="totp"
)
```

```go language="go"
package main

import (
	"context"

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

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

	_, err := client.MultiFactorAuth().CreateUserAuthFactor(context.Background(), "user_01E4ZCR3C56J083X43JQXF3JK5", &workos.MultiFactorAuthCreateUserAuthFactorParams{
		Type: "totp",
	})
	if err != nil {
		panic(err)
	}
}
```

```php language="php"
<?php

use WorkOS\WorkOS;

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

$workos
    ->multiFactorAuth()
    ->createUserAuthFactor(
        userlandUserId: "user_01E4ZCR3C56J083X43JQXF3JK5",
        type: "totp",
    );
```

```java language="java"
import com.workos.WorkOS;
import com.workos.multifactorauth.MultiFactorAuthApi.CreateUserAuthFactorOptions;

WorkOS workos = new WorkOS("sk_example_123456789");

CreateUserAuthFactorOptions options =
    CreateUserAuthFactorOptions.builder().type("totp").build();

workos.multiFactorAuth.createUserAuthFactor("user_01E4ZCR3C56J083X43JQXF3JK5", options);
```

```cs language="dotnet"
using WorkOS;

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

await client.MultiFactorAuth.CreateUserAuthFactorAsync("user_01E4ZCR3C56J083X43JQXF3JK5",
                                                       new MultiFactorAuthCreateUserAuthFactorOptions {
                                                           Type = "totp",
                                                       });
```

```rust language="rust"
use workos::Client;
use workos::multi_factor_auth::CreateUserAuthFactorParams;

#[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
        .multi_factor_auth()
        .create_user_auth_factor(
            "user_01E4ZCR3C56J083X43JQXF3JK5",
            CreateUserAuthFactorParams {
                type_: "totp".into(),
                ..Default::default()
            }
        )
        .await?;

    Ok(())
}
```

:::

## List authentication factors

Lists the [authentication factors](https://workos.com/docs/reference/authkit/mfa/authentication-factor) for a user.

:::code-group{title="Request"}

```bash language="curl"
curl https://api.workos.com/user_management/users/user_01E4ZCR3C56J083X43JQXF3JK5/auth_factors \
  --header "Authorization: Bearer sk_example_123456789"
```

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

const workos = new WorkOS('sk_example_123456789');

const authFactors = await workos.userManagement.listAuthFactors({
  userId: 'user_01E4ZCR3C56J083X43JQXF3JK5',
});

console.log(authFactors.data);
```

```rb language="ruby"
require "workos"

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

WorkOS.client.multi_factor_auth.list_user_auth_factors(userland_user_id: "user_01E4ZCR3C56J083X43JQXF3JK5")
```

```py language="python"
from workos import WorkOSClient

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

client.multi_factor_auth.list_user_auth_factors(
    userland_user_id="user_01E4ZCR3C56J083X43JQXF3JK5"
)
```

```go language="go"
package main

import (
	"context"

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

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

	_, err := client.MultiFactorAuth().ListUserAuthFactors(context.Background(), "user_01E4ZCR3C56J083X43JQXF3JK5")
	if err != nil {
		panic(err)
	}
}
```

```php language="php"
<?php

use WorkOS\WorkOS;

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

$workos
    ->multiFactorAuth()
    ->listUserAuthFactors(userlandUserId: "user_01E4ZCR3C56J083X43JQXF3JK5");
```

```java language="java"
import com.workos.WorkOS;

WorkOS workos = new WorkOS("sk_example_123456789");

workos.multiFactorAuth.listUserAuthFactors("user_01E4ZCR3C56J083X43JQXF3JK5");
```

```cs language="dotnet"
using WorkOS;

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

await client.MultiFactorAuth.ListUserAuthFactorsAsync("user_01E4ZCR3C56J083X43JQXF3JK5");
```

```rust language="rust"
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
        .multi_factor_auth()
        .list_user_auth_factors("user_01E4ZCR3C56J083X43JQXF3JK5")
        .await?;

    Ok(())
}
```

:::

### authentication_challenge

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `object` | "authentication_challenge" | Yes | Distinguishes the authentication challenge object. |
| `id` | string | Yes | The unique ID of the authentication challenge. |
| `created_at` | string | Yes | The timestamp when the challenge was created. |
| `updated_at` | string | Yes | The timestamp when the challenge was last updated. |
| `expires_at` | string | Yes | The timestamp when the challenge will expire. Does not apply to TOTP factors. |
| `authentication_factor_id` | string | Yes | The unique ID of the authentication factor the challenge belongs to. |

### authentication_factor

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `object` | "authentication_factor" | Yes | Distinguishes the authentication factor object. |
| `id` | string | Yes | The unique ID of the factor. |
| `created_at` | string | Yes | The timestamp when the factor was created. |
| `updated_at` | string | Yes | The timestamp when the factor was last updated. |
| `type` | "totp" | Yes | The type of the factor to enroll. The only available option is TOTP. |
| `totp` | object | Yes |  |
| `user_id` | string | Yes | The ID of the [user](/reference/authkit/user). |

### POST /user_management/users/{userlandUserId}/auth_factors

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `type` | "totp" | Yes | The type of the factor to enroll. The only available option is TOTP. |
| `totp_issuer` | string | No | Your application or company name displayed in the user's authenticator app. Defaults to your WorkOS team name. |
| `totp_user` | string | No | The user's account name displayed in their authenticator app. Defaults to the user's email. |
| `totp_secret` | string | No | The Base32-encoded shared secret for TOTP factors. This can be provided when creating the auth factor, otherwise it will be generated. The algorithm used to derive TOTP codes is sha1, the code length is 6 digits, and the timestep is 30 seconds – the secret must be compatible with these parameters. |

#### Parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `userlandUserId` | string | Yes | The ID of the [user](/reference/authkit/user). |

#### Returns

| Field | Type | Description |
| --- | --- | --- |
| `authentication_factor` | object | The [authentication factor](/reference/authkit/mfa/authentication-factor) object that represents the additional authentication method used on top of the existing authentication strategy. |
| `authentication_challenge` | object | The [authentication challenge](/reference/authkit/mfa/authentication-challenge) object that is used to complete the authentication process. |

### GET /user_management/users/{userlandUserId}/auth_factors

#### Parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `userlandUserId` | string | Yes | The ID of the [user](/reference/authkit/user). |
| `before` | string | No | An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. |
| `after` | string | No | An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. |
| `limit` | integer | No | Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`. |
| `order` | "normal" \| "desc" \| "asc" | No | Order the results by the creation time. Defaults to `normal`. |