When building a backend for the TX Text Control Document Editor and Document Viewer, the TX Text Control NuGet packages implement the necessary endpoints and handlers to communicate between the client-side libraries and the backend.

Middleware that checks for an access token is recommended to secure these endpoints. This demo implementation does not create and store access tokens, but illustrates how incoming requests can be checked for an access token. Typically, your actual authorization layer, such as OAuth, creates the access tokens.

The request flow with integrated custom security middleware is illustrated in the following diagram.

TX Text Control Security Middleware

When the client-side Angular package requests resources from the backend, the implemented custom security middleware intercepts the request and validates a security access token sent with the request.

Security Middleware

The security middleware is implemented in the TXSecurityMiddleware class. It basically checks a security token passed as a query string against a stored access token. To illustrate this workflow, the access token is simply hard-coded into the application settings.

namespace TXTextControl
{
public class TXSecurityMiddleware
{
private IConfiguration configuration;
public TXSecurityMiddleware(RequestDelegate next, IConfiguration configuration)
{
m_next = next;
this.configuration = configuration;
}
private RequestDelegate m_next;
public async Task Invoke(HttpContext context)
{
var access_token = this.configuration.GetSection("Security")["AccessToken"];
// Check if the request is a TX Text Control request
if (context.WebSockets.IsWebSocketRequest &&
context.WebSockets.WebSocketRequestedProtocols.Contains("TXTextControl.Web") ||
(context.Request.Query.ContainsKey("access_token") &&
context.GetEndpoint()?.DisplayName?.Contains("TXTextControl.Web.MVC.DocumentViewer") == true))
{
// Retrieve access token from the query string
var accessToken = context.Request.Query["access_token"];
// Showcase only: Easy comparison of tokens
if (accessToken != access_token)
{
throw new UnauthorizedAccessException();
}
else
{
await m_next.Invoke(context);
}
}
else if (m_next != null)
{
await m_next.Invoke(context);
}
}
}
}
view raw test.cs hosted with ❤ by GitHub

The middleware is registered in the Program.cs request pipeline.

app.UseWebSockets();
// Add the TX Security Middleware to the request pipeline
app.UseMiddleware<TXTextControl.TXSecurityMiddleware>();
// TX Text Control specific middleware
app.UseTXWebSocketMiddleware();
view raw test.cs hosted with ❤ by GitHub

The backend also implements an HttpGet method that returns an access token to simulate a common token workflow such as OAuth, where an access token is exchanged for a user id and user secret. In this sample workflow, the method simply returns a valid access token.

[ApiController]
[Route("[controller]")]
public class TXSecurityTokenController : ControllerBase
{
private IConfiguration configuration;
public TXSecurityTokenController(IConfiguration configuration)
{
this.configuration = configuration;
}
[HttpGet]
public SecurityToken Get()
{
return new SecurityToken() { AccessToken = this.configuration.GetSection("Security")["AccessToken"] };
}
}
view raw test.cs hosted with ❤ by GitHub

Requesting Resources

When the client-side Angular application requests resources from the backend, the security token is passed as a query string. The following code shows where the Angular application retrieves the access token from the backend endpoint.

import { HttpClient } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
interface SecurityToken {
accessToken: string;
}
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})
export class AppComponent implements OnInit {
public securityToken: SecurityToken | undefined;
constructor(private http: HttpClient) {}
ngOnInit() {
this.getTokens();
}
getTokens() {
this.http.get<SecurityToken>('/txsecuritytoken').subscribe(
(result) => {
this.securityToken = result;
},
(error) => {
console.error(error);
}
);
}
title = 'tx-security.client';
view raw test.ts hosted with ❤ by GitHub

This retrieved access token is then used as the query string in the webSocketURL property.

<h1 id="tableLabel">Security Token Sample</h1>
<p>
This component demonstrates how to retrieve a security token from the server and how to use it.
</p>
<p *ngIf="!securityToken"><em>Loading... Please refresh once the ASP.NET backend has started. See <a href="https://aka.ms/jspsintegrationangular">https://aka.ms/jspsintegrationangular</a> for more details.</em></p>
<table *ngIf="securityToken">
<thead>
<tr>
<th>AccessToken retrieved:</th>
</tr>
</thead>
<tbody>
<tr>
{{ securityToken.accessToken }}
</tr>
</tbody>
</table>
<div *ngIf="securityToken">
<tx-document-editor width="1000px"
height="500px"
webSocketURL="wss://localhost:7289/TXWebSocket?access_token={{ securityToken.accessToken }}">
</tx-document-editor>
</div>
view raw test.html hosted with ❤ by GitHub

After the token is validated, the editor is initialized.

TX Text Control Security Middleware

Download the complete project from GitHub and test it on your own.