Skip to main content

Security

This section explains how to properly setup your application to use the UpDevs SDK's security functionalities.

Authentication Servers

OAuth

This option is free and provided by the UpDevs SDK by default. You may choose your external OAuth server, but we recommend trying our implementation first.

Open your appsettings.json file and add the following structure at the root level:

{
// ...
"UpDevs": {
"Security": {
"Token": {
"Audience": "MY_JWT_TOKEN_AUDIENCE",
"ClientId": "MY_CLIENT_ID",
"ClientSecret": "MY_SECRET",
"AppBaseUrl": "http://localhost:4200/#",
"Authority": "/realms/MY_REALM",
"UseUpDevsOpenIdAuth": true
},
"OAuth": {
// This is the client ID provided by the OAuth server for
// the client with administrative privileges usually a text.
"AdminCliClientId": "admin-cli",
"AdminCliClientSecret": "MY_ADMIN_CLIENT_SECRET",
// This is the ID identifying the client in the OAuth server,
// usually a GUID.
"OAuthClientId": "MY_OAUTH_CLIENT_ID",
"BaseOAuthUrl": "https://updkc.azurewebsites.net/auth",
"Authority": "/realms/MY_REALM",
"OAuthAdminUrl": "/admin/MY_REALM/console",
"OAuthAdminRealmsUrl": "/admin/realms/MY_REALM"
}
},
"AllowedOrigins": "http://localhost:4200"
}
// ...
}
caution

Make sure to change the values to your real ones.

note

The allowed origins (AllowedOrigins) can be set either in this file or through your Startup.cs file using the AllowedOrigins property.

For this approach, our startup file must inherit from BaseOAuthSecurityStartup. An example can be found below:

// ...
using UpDevs.Sdk.Data.EntityFramework.Extensions;
using UpDevs.Sdk.Rest.Extensions;
using UpDevs.Sdk.Rest.Models;
using UpDevs.Sdk.UserInterface.API.Abstractions;

public class Startup : BaseOAuthSecurityStartup<ExceptionFilter, Guid>
{
public Startup()
{
TypeFromContractsAssembly = typeof(IMyDomainService);
TypeFromDomainContractsAssembly = typeof(IMyDomainService);
TypeFromApplicationAssembly = typeof(MyAppService);
TypeFromDomainAssembly = typeof(MyDomainService);
TypeForMapperConfiguration = typeof(MapperConfiguration);
TypeFromPersistenceAssembly = typeof(DatabaseContext);
UseClaims = false;
}

public override void ConfigureServices(IServiceCollection services)
{
base.ConfigureServices(services);
services
.AddPersistence<DatabaseContext>()
.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo
{
Title = "MyProject",
Version = "v1"
});
});
}

public override void Configure(WebApplication app)
{
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c =>
c.SwaggerEndpoint("/swagger/v1/swagger.json", "MyProject v1")
);
}

base.Configure(app);
}

protected override Dictionary<string, string> GetUpDevsSdkVersions()
{
var baseVersions = base.GetUpDevsSdkVersions();

// TODO: If required, add your custom UpDevs SDK libraries' versions.
// baseVersions.Add(
// "UpDevs.Sdk.Cloud",
// typeof(UpDevs.Sdk.Cloud.Abstractions.IConnection
// ).GetVersion());
// baseVersions.Add(
// "UpDevs.Sdk.Data.EntityFramework",
// typeof(UpDevs.Sdk.Data.EntityFramework.Abstractions.BaseContext
// ).GetVersion());

return baseVersions;
}
}

Once the appsettings.json and Startup.cs files have been setup, we can create the controller that will handle the interactions:

using UpDevs.Sdk.Security.OAuth.Abstractions;

public class OAuthController : BaseOAuthController
{
public OAuthController(IOAuthUsersService oAuthUserService) : base(oAuthUserService) { }
}

Local

Multi Tenancy

Multi tenancy allows your application to manage access of certain groups (tenants) to functionalities. You can, for instance, have one database per client or allow only specific groups of users to access specific functionalities.

Database

To use multi tenants in the UpDevs SDK, you will need to setup one database per tenant. To start we must add the UseMultiTenant property to our appsettings.json file. Also, since we'll be using one connection string per tenant, we must specify each connection string as well:

{
"ConnectionStrings": {
"DefaultConnection": "...",
"Tenant1": "...",
"TenantSuperUser": "...",
"MyClientX": "..."
},
// ...
"UpDevs": {
"Security": {
//...
"UseMultiTenant": true
}
}
}

The keys representing the connection strings used for multiple tenants can be anything you'd like. You could use a descriptive name (like example), the tenant's ID or anything else. The tenant should be provided in the RequestSession. If using the API provided by the UpDevs SDK, the tenant will be automatically filled from the request header. We must also change our database context to inform tenants are in use:

public class DatabaseContext : BaseContext
{
// ...

protected override void Setup(DbContextOptionsBuilder optionsBuilder)
{
if (optionsBuilder.IsConfigured)
{
return;
}

optionsBuilder.UseSqlServer(
GetConnectionString(Constants.Security.UseMultiTenant)
);
}
}

With that change, the UpDevs SDK will now read the information in the appsettings.json file and set multi tenancy up accordingly.

note

Should you need to perform any checks regarding the current tenant, you can access the property Tenant from RequestSession.

Access Control

With tenants, you may also block/allow access to controllers from specific tenants. That's possible by using the attributes AllowOnlyTenants and BlockTenants. AllowOnlyTenants makes sure only the users from the specific list of tenants can access the controller. BlockTenants blocks all tenants informed from accessing the controller. Here's an example where only the tenants SuperAdmin and Admin have access to the endpoint update-secure-data and every tenant, except CommonUsers is allowed to access get-blocked-users:

public class MySecureController : BaseEntityController<IMySecureAppService, 
SecureModel, Guid>
{
[HttpPost("update-secure-data")]
[AllowOnlyTenants("SuperAdmin", "Admin")]
public IActionResult UpdateSecureData([FromBody] SecureModel data)
{
return JsonResponse(GetService<IMySecureAppService>().UpdateSecureData(data));
}

[HttpPost("get-blocked-users")]
[BlockTenants("CommonUsers")]
public IActionResult GetBlockedUsers()
{
return JsonResponse(GetService<IMySecureAppService>().GetBlockedUsers());
}
}
IMPORTANT

Even though you can use them together, it's not mandatory for you to implement a multi tenant database and access control. You are allowed to use one or the other.