Reputation: 23
I have two different client applications that connect to the same API client. I want one to have readonly access (Get calls only) and the other to be able to write as well (Get, Put, Post, and Delete calls). How should I accomplish this?
Final solution:
This is ultimately what I did. It is important to note that this solution requires an additional library.
https://www.nuget.org/packages/IdentityServer4.AccessTokenValidation/ or https://github.com/IdentityServer/IdentityServer4.AccessTokenValidation
services.AddMvcCore(options =>
{
// require at least one of the scopes listed var policy =
ScopePolicy.Create("client_api_readonly", "client_api_fullaccess");
options.Filters.Add(new AuthorizeFilter(policy));
});
services.AddAuthorization(option =>
{
// where the attribute is set, require the following scope
option.AddPolicy("ApiFullAccess", p =>
p.RequireScope("client_api_fullaccess"));
});
Upvotes: 0
Views: 78
Reputation:
In this case you can configure client access by using scopes. Scopes should not be used for authorization, but in this case you want (and can) configure the client access to the resource.
Please note, this is not direct authorization. A scope defines a piece of functionality in the resource. When a client is not able to request a scope then the client is limited to the functionality that is part of the scope(s) that is configured.
But this only work for this particular case because this is a client only and there are no (interactive) users involved.
Suppose you have one resource: myresource
.
And this resource has two scopes, e.g. myresource.read
and myresource.write
.
You can now configure Client.AllowedScopes, where client1 has scope myresource.read
and client2 has the scopes myresource.read
and myresource.write
.
Make sure you implement the two scopes in the resource. You can define policies that look for the certain scope:
services.AddAuthorization(option =>
{
option.AddPolicy("ReadAccess", p => p.RequireScope("myresource.read"));
option.AddPolicy("WriteAccess", p => p.RequireScope("myresource.write"));
});
And deny access to clients that do not have any of the scopes:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(options =>
{
options.JwtBearerEvents = new JwtBearerEvents
{
OnTokenValidated = async context =>
{
var allowedScopes = new List<string> { "myresource.read" , "myresource.write" };
if (!context.Principal.Claims.Any(c => c.Type == "scope" && allowedScopes.Contains(c.Value)))
{
context.Fail("Invalid Scope");
}
}
};
});
In your controllers you can limit access based on the policies, using the Authorize attribute, e.g.
[Authorize("myresource.read")]
public class MyController : ControllerBase
Upvotes: 1
Reputation: 112
Assuming that you have written the API and that your connection to it is authenticated in some fashion, you should be able, within the API, to look up the authenticated user and verify their privileges.
Upvotes: 0