# Token endpoint in ASP.NET

This article presents a simple [token endpoint](../../developer-resources/security/token-endpoint.md) example for creating JSON Web Tokens (JWT) implemented in ASP.NET. The tokens are used by CKEditor Cloud Services to authenticate users.

<a id="dependencies">

## Dependencies

All code examples use the [System.IdentityModel.Tokens.Jwt](https://www.nuget.org/packages/System.IdentityModel.Tokens.Jwt/) library.

If you are using the [package manager console](https://docs.microsoft.com/en-us/nuget/tools/package-manager-console) in Visual Studio, you can run the following:

```bash
Install-Package System.IdentityModel.Tokens.Jwt
```

<a id="examples">

## Examples

When creating a token endpoint to integrate with [Collaboration](../../guides/collaboration/quick-start.md), the token payload should contain the environment ID and user data.

<a id="real-time-collaboration-features">

### Real-time collaboration features

```cs
using System;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Text;
using System.Collections.Generic;

namespace CSTokenExample
{
    class Program
    {
        static string createCSToken(string environmentId, string accessKey)
        {
            var securityKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(accessKey));

            var signingCredentials = new SigningCredentials(securityKey, "HS256");
            var header = new JwtHeader(signingCredentials);

            var dateTimeOffset = new DateTimeOffset(DateTime.UtcNow);

            var payload = new JwtPayload
            {
                { "aud", environmentId },
                { "iat", dateTimeOffset.ToUnixTimeSeconds() },
                { "sub", "user-123" },
                { "user", new Dictionary<string, string> {
                    { "email", "joe.doe@example.com" },
                    { "name", "Joe Doe" }
                } },
                { "auth", new Dictionary<string, object> {
                    { "collaboration", new Dictionary<string, object> {
                        { "*", new Dictionary<string, string> {
                            { "role", "writer" }
                        } }
                    } }
                } }
            };

            var securityToken = new JwtSecurityToken(header, payload);
            var handler = new JwtSecurityTokenHandler();

            return handler.WriteToken(securityToken);
        }

        static void Main(string[] args)
        {
            string accessKey = "w1lnWEN63FPKxBNmxHN7WpfW2IoYVYca5moqIUKfWesL1Ykwv34iR5xwfWLy";
            string environmentId = "LJRQ1bju55p6a47RwadH";

            var tokenString = createCSToken(environmentId, accessKey);

            // Here we are printing the token to the console. In a real usage scenario
            // it should be returned in an HTTP response of the token endpoint.
            Console.WriteLine(tokenString);
        }
    }
}
```

`accessKey` and `environmentId` should be replaced with the keys provided by the [Customer Portal](https://portal.ckeditor.com/) for SaaS or by the [Management Panel](../../onpremises/cs-onpremises/management.md) for the On-Premises application. User data can be taken from the session or the database.

You should then pass the token to the client in an HTTP response of the token endpoint. Do not forget to authenticate the user in your application before you send the token. If the user is unauthenticated, the token endpoint should return an error or redirect to the login page. You should also make sure the token is sent via an encrypted channel.

<a id="ckeditor-ai">

### CKEditor AI

When creating a token endpoint for [CKEditor AI](../../guides/ckeditor-ai/overview.md), the token payload should include AI-specific permissions in the `auth.ai.permissions` array. For a full list of available permissions, see the [Permissions guide](../../guides/ckeditor-ai/permissions.md).

```cs
using System;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Text;
using System.Collections.Generic;

namespace CSTokenExample
{
    class Program
    {
        static string createCSToken(string environmentId, string accessKey)
        {
            var securityKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(accessKey));

            var signingCredentials = new SigningCredentials(securityKey, "HS256");
            var header = new JwtHeader(signingCredentials);

            var dateTimeOffset = new DateTimeOffset(DateTime.UtcNow);

            var payload = new JwtPayload
            {
                { "aud", environmentId },
                { "iat", dateTimeOffset.ToUnixTimeSeconds() },
                { "sub", "user-123" },
                { "user", new Dictionary<string, string> {
                    { "email", "joe.doe@example.com" },
                    { "name", "Joe Doe" }
                } },
                { "auth", new Dictionary<string, object> {
                    { "ai", new Dictionary<string, object> {
                        { "permissions", new List<string> {
                            "ai:conversations:*",
                            "ai:models:agent",
                            "ai:actions:system:*",
                            "ai:reviews:system:*"
                        } }
                    } }
                } }
            };

            var securityToken = new JwtSecurityToken(header, payload);
            var handler = new JwtSecurityTokenHandler();

            return handler.WriteToken(securityToken);
        }

        static void Main(string[] args)
        {
            string accessKey = "w1lnWEN63FPKxBNmxHN7WpfW2IoYVYca5moqIUKfWesL1Ykwv34iR5xwfWLy";
            string environmentId = "LJRQ1bju55p6a47RwadH";

            var tokenString = createCSToken(environmentId, accessKey);

            // Here we are printing the token to the console. In a real usage scenario
            // it should be returned in an HTTP response of the token endpoint.
            Console.WriteLine(tokenString);
        }
    }
}
```

If you use both collaboration and AI, combine both `auth.collaboration` and `auth.ai` in a single token payload.

<a id="easy-image-export-to-pdf-and-import-and-export-to-word">

### Easy Image, Export to PDF and Import and Export to Word

The token endpoint for Easy Image and the Export to Word/PDF features does not require adding user data. You can therefore skip the `user` and `auth` properties in the token payload.

<a id="export-to-pdf-and-import-and-export-to-word-on-premises">

### Export to PDF and Import and Export to Word On-Premises

Tokens for PDF Converter and DOCX Converter On-Premises do not require any additional claims, so you can create the token with an empty payload.

In this implementation, `accessKey` has been replaced by `SECRET_KEY` - a variable set during the [Import and Export to Word](../../onpremises/docx-onpremises/installation.md)/[Export to PDF](../../onpremises/pdf-onpremises/installation.md) On-Premises instance installation.

```cs
using System;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Text;
using System.Collections.Generic;

namespace CSTokenExample
{
    class Program
    {
        static string createCSToken(string secretKey)
        {
            var securityKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secretKey));

            var signingCredentials = new SigningCredentials(securityKey, "HS256");
            var header = new JwtHeader(signingCredentials);

            var dateTimeOffset = new DateTimeOffset(DateTime.UtcNow);

            var payload = new JwtPayload
            {
                { "iat", dateTimeOffset.ToUnixTimeSeconds() }
            };

            var securityToken = new JwtSecurityToken(header, payload);
            var handler = new JwtSecurityTokenHandler();

            return handler.WriteToken(securityToken);
        }

        static void Main(string[] args)
        {
            string secretKey = "w1lnWEN63FPKxBNmxHN7WpfW2IoYVYca5moqIUKfWesL1Ykwv34iR5xwfWLy";

            var tokenString = createCSToken(secretKey);

            // Here we are printing the token to the console. In a real usage scenario
            // it should be returned in an HTTP response of the token endpoint.
            Console.WriteLine(tokenString);
        }
    }
}
```

If you create your own token endpoint, do not forget to authenticate the user before you send the token.

<a id="example-response">

## Example response

The result should be in a plain text format.

```
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJMSlJRMWJqdTU1cDZhNDdSd2FkSCIsImlhdCI6MTY0OTIyOTQyMiwic3ViIjoidXNlci0xMjMiLCJ1c2VyIjp7ImVtYWlsIjoiam9lLmRvZUBleGFtcGxlLmNvbSIsIm5hbWUiOiJKb2UgRG9lIn0sImF1dGgiOnsiY29sbGFib3JhdGlvbiI6eyIqIjp7InJvbGUiOiJ3cml0ZXIifX19fQ._V-HXKKHU1E-saZxk4JTvgXdh1I7793nCEK91ubSZHY
```

<a id="debugging">

## Debugging

For debugging purposes [jwt.io](https://jwt.io) can be used.

---

Full index of the Cloud Services documentation: [llms.txt](../../../llms.txt)
