Skip to content

Commit

Permalink
General refactoring, updated readme.md
Browse files Browse the repository at this point in the history
  • Loading branch information
Farshad DASHTI authored and Farshad DASHTI committed Nov 19, 2024
1 parent 3c4c1fc commit f1bdeac
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 15 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
using System.Diagnostics;
using System.Security.Claims;
using DfE.CoreLibs.Security.Configurations;
using DfE.CoreLibs.Security.Configurations;
using DfE.CoreLibs.Security.Interfaces;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System.Security.Claims;

namespace DfE.CoreLibs.Security.Authorization
{
Expand Down Expand Up @@ -51,7 +50,7 @@ public static IServiceCollection AddApplicationAuthorization(
{
var user = context.User;
var userScopes = GetUserScopes(user).ToArray();

#pragma warning disable S6603
if (userScopes.Any())
{
// User has scopes, check if they have all required scopes
Expand All @@ -68,6 +67,7 @@ public static IServiceCollection AddApplicationAuthorization(
// Require all roles (AND logic)
return requiredRoles.All(role => user.IsInRole(role));
}
#pragma warning restore S6603
});
}
else // "OR" logic
Expand Down
2 changes: 1 addition & 1 deletion src/DfE.CoreLibs.Security/Configurations/TokenSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ public class TokenSettings
public string SecretKey { get; set; } = string.Empty;
public string Issuer { get; set; } = string.Empty;
public string Audience { get; set; } = string.Empty;
public int TokenLifetimeMinutes { get; set; } = 5;
public int TokenLifetimeMinutes { get; set; } = 10;
}
}
74 changes: 64 additions & 10 deletions src/DfE.CoreLibs.Security/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ public void ConfigureServices(IServiceCollection services, IConfiguration config
services.AddCustomClaimProvider<UserProfileClaimProvider>(); // if you need to add custom/ non-security claims
}
```

#### 2\. Configuring Policies and Claims in `appsettings.json`

Expand All @@ -44,17 +43,20 @@ Define your authorization policies in `appsettings.json` under the `Authorizatio
{
"Name": "CanRead",
"Operator": "OR",
"Roles": [ "API.Read" ]
"Roles": [ "Reader" ],
"Scopes": [ "SCOPE.API.Read" ]
},
{
"Name": "CanReadWrite",
"Operator": "AND",
"Roles": [ "API.Read", "API.Write" ]
"Roles": [ "Reader", "Writer" ],
"Scopes": [ "SCOPE.API.Read", "SCOPE.API.Write" ]
},
{
"Name": "CanReadWritePlus",
"Name": "CanReadWriteDelete",
"Operator": "AND",
"Roles": [ "API.Read", "API.Write" ],
"Roles": [ "Reader", "Writer", "Deleter" ],
"Scopes": [ "SCOPE.API.Read", "SCOPE.API.Write", "SCOPE.API.Delete" ],
"Claims": [
{
"Type": "API.PersonalInfo",
Expand All @@ -66,9 +68,61 @@ Define your authorization policies in `appsettings.json` under the `Authorizatio
}
}
```

#### 3\. Using Policy Customization to add a new Requirement

**Key Points:**

* **Policy Names**: Each policy must have a unique `Name`.
* **Operator**: Defines the logical operation (`AND` or `OR`) used to evaluate Roles and Scopes.
* **Roles**: A list of roles that can satisfy the policy based on the operator.
* **Scopes**: A list of scopes that can satisfy the policy based on the operator. **Note**: Scopes are equivalent to roles but are primarily used in API scenarios, especially with OBO tokens.
* **Claims**: Additional claim requirements that must be met for the policy to succeed.

### 3\. Creating Authorization Policies

For each policy defined in the configuration:

* **Operator Logic**:
* `AND`:
* **With Scopes**: The user must have **all** specified scopes.
* **Without Scopes**: The user must have **all** specified roles.
* `OR`:
* The user must have **at least one** of the specified scopes **or** **at least one** of the specified roles.
* **Claims**: If the policy includes claims, the user must possess the specified claims.

**Note**: Scopes are only needed if this configuration is for an API and the API will be accessed by another client and is provided with an OBO Token.


### Understanding Scopes and Roles in Authorization Policies

**Scopes vs. Roles**

* **Roles**:
* **Definition**: Represent broader permissions or access levels within an application.
* **Usage**: Commonly used in traditional authentication scenarios where users are assigned roles that determine their access rights.
* **Example**: `Reader`, `Writer`, `Admin`.
* **Scopes**:
* **Definition**: Represent granular permissions, primarily used in OAuth 2.0 and OpenID Connect scenarios.
* **Usage**: Employed in API-centric architectures where tokens (like JWTs) contain scopes that define the level of access granted to client applications.
* **Example**: `SCOPE.API.Read`, `SCOPE.API.Write`.

**Key Equivalence:** Within authorization policies, **Scopes** and **Roles** are treated equivalently. A policy can require either specific roles or scopes, depending on the user's token type.


**When to Use Scopes**


* **API Scenarios**:
* If your application serves as an **API** that exposes **Scopes**, use scopes within your authorization policies.
* Scopes are particularly relevant when dealing with **On-Behalf-Of (OBO)** tokens, where scopes are included instead of roles.
* **OBO Tokens**:
* **Definition**: OBO tokens allow a service (like an API) to act on behalf of a user, typically used in multi-tiered applications.
* **Behavior**: These tokens contain **Scopes** instead of **Roles**, representing the delegated permissions.
* **Policy Implication**: Authorization policies should be configured to recognize and evaluate scopes appropriately when processing OBO tokens.



#### 4\. Using Policy Customization to add a new Requirement

To create custom requirements, implement the `ICustomAuthorizationRequirement` interface and register them using the `RequirementRegistry`.

Expand Down Expand Up @@ -127,7 +181,7 @@ public class LocationAccessHandler : AuthorizationHandler<LocationAccessRequirem
```

#### 4\. Adding Custom Claim Providers
#### 5\. Adding Custom Claim Providers

Custom claim providers allow you to fetch claims dynamically based on the user’s identity. Implement `ICustomClaimProvider` to create a custom claim provider and register it in `Startup.cs`.

Expand All @@ -152,13 +206,13 @@ services.AddCustomClaimProvider<UserProfileClaimProvider>();
```
#### 5\. Applying Policies in Controllers
#### 6\. Applying Policies in Controllers

Once configured, use `[Authorize(Policy = "PolicyName")]` to apply policies on controllers or specific actions.


```csharp
[Authorize(Policy = "AdminOnly")]
[Authorize(Policy = "CanReadWrite")]
public class AdminController : Controller
{
public IActionResult Dashboard() => View();
Expand Down

0 comments on commit f1bdeac

Please sign in to comment.