# Creating Security Profiles

> Create OAuth security profiles with a client ID, client secret and redirect URIs in the admin portal, with the /admin/securityprofiles endpoints or in C#.

- **Product:** DS Server
- **Section:** Documentation
- **Kind:** Topic
- **Path:** DS Server > Administration and Settings > Creating Security Profiles
- **3031 words**
- **Web URL:** https://docs.textcontrol.com/ds-server/administration/security-profiles/
- **LLMs URL:** https://docs.textcontrol.com/ds-server/administration/security-profiles/llms.txt
- **LLMs-Full URL:** https://docs.textcontrol.com/ds-server/administration/security-profiles/llms-full.txt

---

A security profile is the set of OAuth client credentials that one application uses to get access tokens from DS Server: a client ID, a client secret and the redirect URIs the application may receive authorization codes at. You create as many profiles as you need, typically one per application, so that each application has its own credentials and you can revoke them one at a time. Create at least one profile before you [enable OAuth](https://docs.textcontrol.com/ds-server/administration/oauth/llms-full.txt), because from then on every request to the DocumentProcessing Web API, the Document Editor and the Document Viewer needs a token issued for a profile.

### What a Security Profile Holds

| Field in the portal | What it is |
|---|---|
| **Name** | A name that tells you which application uses the profile |
| **Authorized Redirect URIs** | The addresses in your application that DS Server may send an authorization code to. Needed for the authorization code flow. |
| **Allow “Client Credentials” grant type** | Whether the profile may get tokens with the client ID and secret alone. Off by default, see [OAuth Grant Types](https://docs.textcontrol.com/ds-server/administration/oauth-grant-types/llms-full.txt). |
| **Expiry date** | An optional date after which the profile's tokens are refused |
| **Client ID** | Generated by DS Server: `dsserver.` followed by 32 letters and digits |
| **Client Secret** | Generated by DS Server: 32 letters and digits |
| **Creation date** | The date the profile was created |

DS Server stores the profiles in its *Admin.db* database. Each installation has its own profiles; [Authentication Servers](https://docs.textcontrol.com/ds-server/administration/authentication-servers/llms-full.txt) describes how several servers accept the tokens of one server's profiles.

### Create a Profile in the Portal

1. Sign in to the admin portal and click **Security Profiles** in the navigation bar. The page lists the existing profiles with their **Profile Name** and **Client ID**.

    ![The Security Profiles page with three profiles](https://docs.textcontrol.com/assets/img/ds-server/portal-security-profiles.26f8dcfc.webp)
2. Click **+ Create new profile**.
3. On the **Create Security Profile** page, enter a **Name** and click **Create**.

    ![The Create Security Profile page with a name entered](https://docs.textcontrol.com/assets/img/ds-server/portal-create-profile.22141ede.webp)
4. The page changes to **Edit Security Profile** and shows the generated **Client ID** and **Client Secret**. The buttons beside them copy the values to the clipboard.

    ![The new profile with its client ID, client secret and expiry date](https://docs.textcontrol.com/assets/img/ds-server/portal-profile-details.48eafb12.webp)
5. Add the redirect URIs your application needs, as the next section describes, and click **Done**. DS Server saves the profile and returns to the list.

Keep the client secret on your server. Anyone who has the client ID and the secret can request tokens for the profile.

### Add the Redirect URIs

When an application uses the authorization code flow, DS Server sends the authorization code only to a redirect URI that is listed in the profile. The ASP.NET Core client packages use this flow when you set `OAuthSettings.RedirectUri`, and they provide the callback endpoint themselves at a fixed path of your application:

| Component | Redirect URI to add |
|---|---|
| Document Editor (`TXTextControl.DocumentServices.DocumentEditor`) | `https://yourdomain.com/textcontrol/documenteditor/auth/callback` |
| Document Viewer (`TXTextControl.DocumentServices.DocumentViewer`) | `https://yourdomain.com/textcontrol/documentviewer/auth/callback` |
| DocumentProcessing (`TXTextControl.DocumentServices.DocumentProcessing`) | `https://yourdomain.com/textcontrol/documentprocessing/auth/callback` |

Replace `https://yourdomain.com` with the address of your application, such as `https://localhost:7194` while you develop it. The URI your application sends has to match an entry. DS Server 5.0.2 ignores upper and lower case, but a different scheme, port or path, a trailing slash or a query string is a mismatch.

1. On the **Edit Security Profile** page, click **+ Add URI**. An empty text box with a delete button appears; it is marked red until it holds a valid URL.
2. Enter the redirect URI. Click **+ Add URI** again for each further URI, for example when one application uses both the Document Editor and the Document Viewer.

    ![Two redirect URIs added to a security profile](https://docs.textcontrol.com/assets/img/ds-server/portal-add-redirect-uri.c0a1788e.webp)
3. Click **Done** for a new profile, or **Save** for an existing one.

A profile that has no redirect URI and doesn't allow the client credentials grant type is marked in the list with a badge on its edit icon and the tooltip "Profile has no redirect URIs defined." Such a profile can't get tokens. A profile for the client credentials grant type only needs no redirect URI and has no badge.

### Edit, Expire or Delete a Profile

- **Edit.** Click the edit icon of a profile (tooltip "Edit profile"). The **Edit Security Profile** page opens with the buttons **Save** and **Close**. After **Save**, a green note confirms "Editing Profile Changes saved successfully." The client ID and the secret can't be changed.

    ![The confirmation after saving a profile](https://docs.textcontrol.com/assets/img/ds-server/portal-profile-saved.cf58c575.webp)
- **Expire.** Set an **Expiry date** and save. After that date, DS Server refuses every request made with a token of the profile with status 401, including tokens issued before. The token endpoint still issues new tokens, but they are refused as well. Clear the date to make the tokens valid again.
- **Delete.** Click the delete icon (tooltip "Delete profile") and confirm **Are you sure you want to delete the profile?** with **Delete**. The tokens already issued for the profile become invalid at once, and its client ID can no longer get new ones.

    ![The Confirm Delete dialog](https://docs.textcontrol.com/assets/img/ds-server/portal-delete-profile.cf0d77d4.webp)

### Manage Profiles With the Web API

The [administration endpoints](https://docs.textcontrol.com/ds-server/reference/web-api/administration/llms-full.txt) create and change profiles from a script, for example to set up several servers the same way. They take the admin user name and password in a Basic `Authorization` header. This request creates a profile that allows the client credentials grant type and has one redirect URI:

```bash
curl --request POST 'http://localhost:5000/admin/securityprofiles' \
    --user 'admin:<admin password>' \
    --header 'Content-Type: application/json' \
    --data-raw '{
        "name": "Invoice App",
        "allowClientCredentialsGrantType": true,
        "clientCredentials": {
            "authorizedRedirectUris": [
                "https://yourdomain.com/textcontrol/documenteditor/auth/callback"
            ]
        }
    }'
```

DS Server answers with the ID of the new profile, such as `2`. `allowClientCredentialsGrantType` and `expiryDate` belong at the top level of the object; inside `clientCredentials`, DS Server 5.0.2 ignores them. Without `id` and `secret` in `clientCredentials`, DS Server generates the client ID and the secret. A client ID that another profile already uses gets status 400 and "A profile with the given client ID already exists."

[GET /admin/securityprofiles/{id}](https://docs.textcontrol.com/ds-server/reference/web-api/administration/securityprofiles-id/get/llms-full.txt) returns the profile with its generated `clientCredentials`:

```json
{
    "id": 2,
    "name": "Invoice App",
    "allowClientCredentialsGrantType": true,
    "clientCredentials": {
        "id": "dsserver.<32 letters and digits>",
        "secret": "<32 letters and digits>",
        "authorizedRedirectUris": [
            "https://yourdomain.com/textcontrol/documenteditor/auth/callback"
        ]
    },
    "creationDate": "2026-09-29T07:41:12.53+02:00",
    "expiryDate": null,
    "isExpired": false,
    "hasRedirectUriAuthorized": true
}
```

| Task | Endpoint | Body |
|---|---|---|
| List the profile IDs | [GET /admin/securityprofiles](https://docs.textcontrol.com/ds-server/reference/web-api/administration/securityprofiles/get/llms-full.txt) | None; returns an array such as `[1, 2]` |
| Create a profile | [POST /admin/securityprofiles](https://docs.textcontrol.com/ds-server/reference/web-api/administration/securityprofiles/post/llms-full.txt) | The profile, as above |
| Read a profile | [GET /admin/securityprofiles/{id}](https://docs.textcontrol.com/ds-server/reference/web-api/administration/securityprofiles-id/get/llms-full.txt) | None |
| Delete a profile | [DELETE /admin/securityprofiles/{id}](https://docs.textcontrol.com/ds-server/reference/web-api/administration/securityprofiles-id/delete/llms-full.txt) | None |
| Allow or forbid client credentials | [PATCH .../allowclientcredentialsgranttype](https://docs.textcontrol.com/ds-server/reference/web-api/administration/securityprofiles-id-allowclientcredentialsgranttype/patch/llms-full.txt) | `true` or `false` |
| Set or clear the expiry date | [PATCH .../expirydate](https://docs.textcontrol.com/ds-server/reference/web-api/administration/securityprofiles-id-expirydate/patch/llms-full.txt) | A date such as `"2027-06-30T00:00:00"`, or `null` |
| Replace the redirect URIs | [PATCH .../clientcredentials/authorizedredirecturis](https://docs.textcontrol.com/ds-server/reference/web-api/administration/securityprofiles-id-clientcredentials-authorizedredirecturis/patch/llms-full.txt) | A JSON array of strings |

The PATCH bodies are JSON with the content type `application/json`. An ID that doesn't exist gets status 404 with an empty body.

### Manage Profiles With the Admin Package

In a .NET application, the [TXTextControl.DocumentServices.Admin](https://docs.textcontrol.com/ds-server/reference/dotnet-api/txtextcontrol-documentservices-admin/llms-full.txt) package calls the same endpoints. Install it from nuget.org:

```bash
dotnet add package TXTextControl.DocumentServices.Admin
```

This console application creates a profile, adds the redirect URI of the Document Editor and prints the generated credentials:

```csharp
using TXTextControl.DocumentServices.Admin;

// Connect with the service URL and the admin password
Admin admin = new Admin("http://localhost:5000", "<admin password>");

// Create the profile and keep its ID
SecurityProfile profile = new SecurityProfile("Invoice App");
int id = await admin.AddSecurityProfile(profile);

// Add the callback of the Document Editor package
await admin.UpdateAuthorizedRedirectUris(id, new string[] {
    "https://yourdomain.com/textcontrol/documenteditor/auth/callback" });

// Read the client ID and the client secret DS Server generated
SecurityProfile created = await admin.GetSecurityProfile(id);
Console.WriteLine($"Client ID: {created.ClientCredentials.ID}");
Console.WriteLine($"Client secret: {created.ClientCredentials.Secret}");
```

The code works as follows:

- `new Admin(serviceUrl, password)` connects to DS Server with the password of the `admin` user.
- The `SecurityProfile` constructor takes the name of the profile. `AddSecurityProfile` returns the ID of the new profile.
- `UpdateAuthorizedRedirectUris` replaces the list of redirect URIs. `UpdateAllowClientCredentialsGrantType` and `UpdateExpiryDate` change the other settings. `UpdateExpiryDate` takes a `DateTime` and can't clear the date; the PATCH endpoint with `null` does.
- `GetSecurityProfile` returns the profile; its `ClientCredentials` hold the `ID` and the `Secret`.
- Every method returns a task. A failed request throws a `ServiceRequestException`, whose `StatusCode` is, for example, `NotFound` for an unknown ID or `Unauthorized` for a wrong password.

`GetSecurityProfileIds` and `DeleteSecurityProfile` list and delete profiles. [ASP.NET Core](https://docs.textcontrol.com/ds-server/client-libraries/aspnet-core/#admin) lists every method of the package.

### Next Steps

- [Enable OAuth](https://docs.textcontrol.com/ds-server/administration/oauth/llms-full.txt): switch on the token check once your applications have their profiles.
- [OAuth Grant Types](https://docs.textcontrol.com/ds-server/administration/oauth-grant-types/llms-full.txt): decide between the authorization code and the client credentials grant type.
- [Client-Side Libraries](https://docs.textcontrol.com/ds-server/client-libraries/llms-full.txt): pass the client ID and secret to the Document Editor, the Document Viewer and DocumentProcessing.

---

## Nearby

- **Previous:** [Licensing](https://docs.textcontrol.com/ds-server/administration/licensing/llms-full.txt)
- **Next:** [Enable OAuth](https://docs.textcontrol.com/ds-server/administration/oauth/llms-full.txt)
