Asp.Net BoilerPlate - PermissionManager.GetAllPermissions() not getting a new permission - aspnetboilerplate

I created a default solution from BoilerPlate's website with angular.
I need to create a new permission to assign to a user. So I added it in my authorization provider:
public class PilotoConciliacaoAuthorizationProvider : AuthorizationProvider
{
public override void SetPermissions(IPermissionDefinitionContext context)
{
context.CreatePermission(PermissionNames.Pages_Users, L("Users"));
context.CreatePermission(PermissionNames.Pages_Users_Activation, L("UsersActivation"));
context.CreatePermission(PermissionNames.Pages_Roles, L("Roles"));
context.CreatePermission(PermissionNames.Pages_Tenants, L("Tenants"), multiTenancySides: MultiTenancySides.Host);
context.CreatePermission(PermissionNames.Pages_CadastrarPdv, L("TituloCadastrarPdv"), multiTenancySides: MultiTenancySides.Host);
}
private static ILocalizableString L(string name)
{
return new LocalizableString(name, PilotoConciliacaoConsts.LocalizationSourceName);
}
}
In the case, it's PermissionNames.Pages_CadastrarPdv.
I've created the constant and the localizable resource.
But when I run the GetAllPermissions service, it only gets 3 of them:
"result": {
"items": [
{
"name": "Pages.Roles",
"displayName": "Funções",
"description": null,
"id": 0
},
{
"name": "Pages.Users.Activation",
"displayName": "Users activation",
"description": null,
"id": 0
},
{
"name": "Pages.Users",
"displayName": "Usuários",
"description": null,
"id": 0
}
]
},
"targetUrl": null,
"success": true,
"error": null,
"unAuthorizedRequest": false,
"__abp": true
What am I missing?
Thanks in advance.

What happening is that you've specified this permission just for host user, as I can see you are logged as a tenant so you won't see this permission neither tenant permission.
If you need MultiTenancy active and you need this permission to all users you have to remove this section of permission especification and put it like this:
context.CreatePermission(PermissionNames.Pages_CadastrarPdv, L("TituloCadastrarPdv"));
If you don't need to use MultiTenancy, you can disable it on:
YourProjectName.Core\YourProjectNameConsts.cs there you'll find a variable
public const bool MultiTenancyEnabled = true; change it to false if you don't need to use it.
You can call ready the entire documentation for Authorization here:
AspnetBoilerplate - Authorization

Related

Set PrivilegeDepth with Microsoft CDS Web API

I'm trying to create an application user, along with its Security Role, for my Common Data Service environment using only the Web API. I've managed to create both the User, the Role and associate some Privileges to the Role. The only thing I can't do, is set the PrivilegeDepth of the RolePrivilege association.
This is the request payload I'm using to create the role with a few privileges:
{
"businessunitid#odata.bind": "/businessunits(6efad0b7-160b-eb11-a812-000d3ab2a6be)",
"name": "Security Role Test",
"iscustomizable": {
"Value": true,
"CanBeChanged": true,
"ManagedPropertyLogicalName": "iscustomizableanddeletable"
},
"canbedeleted": {
"Value": true,
"CanBeChanged": true,
"ManagedPropertyLogicalName": "canbedeleted"
},
"roleprivileges_association#odata.bind": [
"/privileges(2493b394-f9d7-4604-a6cb-13e1f240450d)",
"/privileges(707e9700-19ed-4cba-be06-9d7f6e845383)",
"/privileges(e62439f6-3666-4c0a-a732-bde205d8e938)",
"/privileges(e3f45b8e-4872-4bb5-8b84-01ee8f9c9da1)",
"/privileges(f36ff7e9-72b9-4882-afb6-f947de984f72)",
"/privileges(886b280c-6396-4d56-a0a3-2c1b0a50ceb0)"
]
}
The RolePrivileges are all created with the lowest depth (User). Anyone knows how to set different depths?
Also, is there a better way to assign privileges to the role? Like, upload an XML with the desired privileges to an endpoint which associates it with the role? And is there a better way to specify the privileges without having to know their GUIDs?
I would really appreciate it if you could help me with this. Thanks!
This should be the payload for setting depth like user, local, etc. Make sure to test this, I didn’t get a chance to test it now. Read more
"roleprivileges_association#odata.bind": [
{
"privilegeid#odata.bind" : "/privileges(2493b394-f9d7-4604-a6cb-13e1f240450d)",
"depth" : 1
},
]
Regarding the dynamic guid values instead of hard coding, just make another service call to pull all the privileges and iterate them. Read more
So I found the solution to set the Privilege depth. There's an action for that, AddPrivelegesRole.
Example:
POST https://org12345.crm4.dynamics.com/api/data/v9.0/roles(1b3df93a-070f-eb11-a813-000d3a666701)/Microsoft.Dynamics.CRM.AddPrivilegesRole
{
"Privileges": [
{
"Depth": "0",
"PrivilegeId": "886b280c-6396-4d56-a0a3-2c1b0a50ceb0",
"BusinessUnitId": "6efad0b7-160b-eb11-a812-000d3ab2a6be"
},
{
"Depth": "1",
"PrivilegeId": "7863e80f-0ab2-4d67-a641-37d9f342c7e3",
"BusinessUnitId": "6efad0b7-160b-eb11-a812-000d3ab2a6be"
},
{
"Depth": "2",
"PrivilegeId": "d26fe964-230b-42dd-ad93-5cc879de411e",
"BusinessUnitId": "6efad0b7-160b-eb11-a812-000d3ab2a6be"
},
{
"Depth": "3",
"PrivilegeId": "ca6c7690-c935-46b3-bfd2-abb306c2acc0",
"BusinessUnitId": "6efad0b7-160b-eb11-a812-000d3ab2a6be"
}
]
}

Link AccessToken to a user in Loopback

I wanted to add a custom attribute (expireAt) to the access token for it to be used by MongoDB to automatically remove the expired access token when expired.
Adding the custom attribute while creating the access token using AccessToken model is working well:
const ttl = 600;
const expireAt = new Date();
expireAt.setSeconds(expireAt.getSeconds() + ttl);
const token = await AccessToken.create({ ttl, expireAt });
However, when I want to create an access token for a user, I can't add the custom attribute exprieAt when creating the token, so I have create first, and then update it:
const ttl = 600;
const expireAt = new Date();
expireAt.setSeconds(expireAt.getSeconds() + ttl);
// Create the access token for the user
const token = await user.createAccessToken(options);
// Update token to set the custom date and time to expire
token.expireAt = expireAt;
token.save();
// Return the token together with the user data
return Object.assign({}, token.toJSON(), { user });
Is there a way I can create the token for a user with the custom attribute (either using instance method or model method is fine), without doing two steps - create and update?
So it seems that AccessToken model has the relationship set up with the user via userId attribute (ref: https://github.com/strongloop/loopback/blob/master/common/models/access-token.json#L27).
{
"name": "AccessToken",
"properties": {
"id": {
"type": "string",
"id": true
},
"ttl": {
"type": "number",
"ttl": true,
"default": 1209600,
"description": "time to live in seconds (2 weeks by default)"
},
"scopes": {
"type": ["string"],
"description": "Array of scopes granted to this access token."
},
"created": {
"type": "Date",
"defaultFn": "now"
}
},
"relations": {
"user": {
"type": "belongsTo",
"model": "User",
"foreignKey": "userId"
}
},
"acls": [
{
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "DENY"
}
]
}
To link the token to the user, we only need to pass in the value userId:
AccessToken.create({ ttl, expireAt, userId });

Spring MVC Converter and Swagger doc: how to?

I use converters in my Spring MCV controllers. In this example, the String from the path variable is mapped into a UserId:
#GetMapping(path = "/user/{user-id}")
public User get(#Parameter(description = "User id", required = true, example = "3fa85f64-5717-4562-b3fc-2c963f66afa6")
#PathVariable("user-id")
UserId userId) {
return userService.get(userId)
}
It seems to annoy Swagger as the generated doc requires an object as parameter and not a plain string:
...
"/api/v1/user/{user-id}": {
"get": {
"operationId": "get",
"parameters": [
{
"name": "user-id",
"in": "path",
"schema": {
"$ref": "#/components/schemas/UserId"
},
}
],
...
with the UserId schema:
"UserId": {
"type": "object",
"properties": {
"value": {
"type": "string",
"format": "uuid"
}
}
}
And thus the Swagger UI cannot be used because either the parameter is considered as invalid when a single string is provided, either the data is actually invalid when the object format is used.
What is an option to fix that?
To achieve that, the schema parameter of the #Parameter annotation is the answer.
The above example becomes:
#Parameter(description = "User id",
required = true,
schema = #Schema(implementation = String.class), // this is new
example = "3fa85f64-5717-4562-b3fc-2c963f66afa6")

Problem creating "Global-OptionSet" attribute using CRM Dynamics WebApi

I'm trying to create a "Global OptionSet"-attribute (sd_MyAttribute) for an existing entity (entity ID = 70816501-edb9-4740-a16c-6a5efbc05d84) via Dynamics CRM WebAPI.
The JSON I send is this using method "POST":
{
"#odata.type": "Microsoft.Dynamics.CRM.PicklistAttributeMetadata",
"OptionSet": {
"#odata.type": "Microsoft.Dynamics.CRM.OptionSetMetadata",
"IsGlobal": true,
"Name": "sd_MyPickList",
"OptionSetType": "Picklist",
"MetadataId": "a50cfc0a-e206-ea11-a811-000d3ab82e70"
},
"AttributeType": "Picklist",
"SchemaName": "sd_MyAttribute",
"Description": {
"#odata.type": "Microsoft.Dynamics.CRM.Label",
"LocalizedLabels": [
{
"#odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel",
"Label": "This is the attribute I want to create.",
"LanguageCode": 1033
}
]
},
"DisplayName": {
"#odata.type": "Microsoft.Dynamics.CRM.Label",
"LocalizedLabels": [
{
"#odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel",
"Label": "This is the attribute I want to create.",
"LanguageCode": 1033
}
]
},
"RequiredLevel": {
"Value": "None",
"CanBeChanged": true
}
}
I expected to get a status 204 response, indicating that a new Picklist attribute on the entity using the sd_MyPickList option set has been created.
Unfortunately, the response is:
{
"error": {
"code": "0x80048403",
"message": "Only Local option set can be created through the attribute create. IsGlobal flag must be set to 'false'.",
"innererror": {
"message": "Only Local option set can be created through the attribute create. IsGlobal flag must be set to 'false'.",
"type": "Microsoft.Crm.CrmException",
"stacktrace": " ...)"
}
}
}
There is already an issue in the github project (see https://github.com/MicrosoftDocs/dynamics-365-customer-engagement/issues/601), but I wonder whether there is a way around this problem - what json do I need to send to create an attribute adressing a global option set? Is there someone who has successfully created such an entity attribute via web-api?
There is a usecase, I don't have the ability to use an existing library for that and importing a solution is not an option in my case.
Would be perfect if someone can provide a simple json that can be send e.g. using the Contact entity and any global optionset.
Finally, I found a way to accomplish what I need. To specify the global option set I need to use the "#odata.bind" action in the JSON data. For an attribute "sd_MyAttribute" that uses the global OptionSet with the MetaDataId "62654906-7A0b-ea11-a817-000d3ab826fd", I need to do POST:
{
"#odata.type": "Microsoft.Dynamics.CRM.PicklistAttributeMetadata",
"GlobalOptionSet#odata.bind": "/GlobalOptionSetDefinitions(62654906-7A0b-ea11-a817-000d3ab826fd)",
"AttributeType": "Picklist",
"SchemaName": "sd_MyAttribute",
"Description": { ... },
"DisplayName": { ... },
"RequiredLevel": { ... }
}
If the entity does have the MetaDataId "70916b01-edb2-4840-a16b-6a2efbc75d84", the URI for the POST would be "/api/data/v9.0/EntityDefinitions(70916b01-edb2-4840-a16b-6a2efbc75d84)/Attributes" (logical- or schema-names are not supported).
Hope my question and answer does help someone who gets the same error message.

Getting access token claims in claims principal in IdentityServer4

I'm trying to get my head around oAuth2/IdentityServer4.
Using the sample application at
https://github.com/IdentityServer/IdentityServer4.Samples/tree/dev/Quickstarts/3_ImplicitFlowAuthentication
The following code in the MVC application:
#foreach (var claim in User.Claims)
{
<dt>#claim.Type</dt>
<dd>#claim.Value</dd>
}
Returns what appears to be identity token claims
nbf
1467173142
exp
1467173442
iss
http://localhost:5000
aud
mvc
nonce
636027699106782287.MDI0YzI5MTQtYmQxNy00MDllLWJmYzQtZjBhYzI2MGNjYmE3MDFmNzg1YmUtM2Y5ZC00YjBiLWEzOGItN2Q3ODRiODJlYjFl
iat
1467173142
c_hash
H2i5QeJKlHM5-s8vUTYlOw
sid
42b58d38e2b7c6cc653492742a08840b
sub
818727
auth_time
1467170555
idp
idsvr
name
Alice Smith
given_name
Alice
family_name
Smith
website
http://alice.com
amr
pwd
The following code in the API project
var claims = User.Claims.Select(c => new { c.Type, c.Value });
return new JsonResult(claims);
Returns what appears to be access token claims
{
"Type": "nbf",
"Value": "1467173142"
},
{
"Type": "exp",
"Value": "1467176742"
},
{
"Type": "iss",
"Value": "http://localhost:5000"
},
{
"Type": "aud",
"Value": "http://localhost:5000/resources"
},
{
"Type": "client_id",
"Value": "mvc"
},
{
"Type": "scope",
"Value": "openid"
},
{
"Type": "scope",
"Value": "profile"
},
{
"Type": "scope",
"Value": "api1"
},
{
"Type": "sub",
"Value": "818727"
},
{
"Type": "auth_time",
"Value": "1467170555"
},
{
"Type": "idp",
"Value": "idsvr"
}
Notice the code is essentially the same (return claims in the user identity principle) and lack of name/email but the inclusion of scope claims in the API example.
The token flow is essentially IdentityServer4 => MVC Project => API Project. Obviously the MVC project has both the identityToken and access token but it's not load the access token int User.Claims.
My goal is to have the scope claims available in User in the MVC project so that I can setup policies to work the Authorize attribute section off my MVC methods.
Startup for the API project is here: https://github.com/IdentityServer/IdentityServer4.Samples/blob/dev/Quickstarts/3_ImplicitFlowAuthentication/src/Api/Startup.cs
Startup for the MVC project is here:
https://github.com/IdentityServer/IdentityServer4.Samples/blob/dev/Quickstarts/3_ImplicitFlowAuthentication/src/Api/Startup.cs
Thanks,
dave
The question is kind of invalid, but I'll leave it here with reasons why and a solution to save others time.
Firstly, there are two tokens for two different purposes.
The Access Token: Describes the client, which is the software that uses the API. Any claims in here are granting the client access to API endpoints.
The Identity Token: This describes the User, or the human that uses the software that uses the API.
The original question was asking how to view Client related scopes in an Identity token, which obviously isn't valid.
However, you can include Identity scopes in an Identity token.
To do this, set Type to ScopeType.Resource and set IncludeAllClaimsForUser to true, as follows
new Scope()
{
Name = "ManageUsers",
IncludeAllClaimsForUser = true,
Type = ScopeType.Resource
},

Resources