To add ADFS 3.0 authentication in our SPA we use the javascript sample and one (wsfed) external identityprovider, and we also add a local api for the SPA client
We also added a custom view to the login process, where the user could "Select WorkingContext" and we could set an additional claim.
Problem: How to add and retrive that additional claim?
Since we simply need the a few of the claim from ws federation, we've made a super simple callback where we just do the following (I'm answering the questions from the docs)
Handling the callback and signing in the user
inspect the identity returned by the external provider.
Yes, we get correct claims from wsfed
make a decision how you want to deal with that user. This might be different based on the fact if this is a new user or a returning user. New users might need additional steps and UI before they are allowed
in.
No additional steps required
probably create a new internal user account that is linked to the external provider.
No, we don't need the user, we just need the a few of the claims from wsfed, so we just return a TestUser based on the wsfed sub in FindUserFromExternalProvider
store the external claims that you want to keep.
Do we need to store the claims, will the claims not be embedded in the jwt token, and the token simply validated?
delete the temporary cookie
ok
sign-in the user
Here we would like to show a custom ui where the user should select a "workingcontext", and we could add the "workingcontext" as an additional claim.
Assuming the above is valid, how can we in step 6 add the extra claim?
await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.SubjectId, user.Username, true, context?.ClientId));
doesn't seem to give any ways to add claims.
This is how we try to pass the additional claims through the login process:
var isuser = new IdentityServerUser(user.SubjectId)
{
DisplayName = user.Username,
IdentityProvider = provider,
AdditionalClaims = additionalLocalClaims
};
await HttpContext.SignInAsync(isuser, localSignInProps);
We just need to implement the IProfileService, that's all.
Related
That's my question. I am using Hasura, and defining 'user' permissions.
Users are of course allowed to modify their own information, and not allowed to insert new records into my users table.
But when they signup, they should be allowed to insert themselves. So how can I define this permission?
To make my scenario more clear:
I have a React app, that uses an external OpenID provider. So a new user signs up there, and the provider returns a JWT to my app, containing a user I've never seen before.
My app does not know that, it just uses the access token to send to the Hasura backend to retrieve further info about this user, using the 'user' role. But it uses a query which will automatically insert the user if not found.
There's really not a safe way to allow sign-ups without involving a backend service. It is a very bad idea to allow anonymous inserts into your user table, even if you added a unique constraint against a user ID or email address.
If you have the option of using NextJS, see the Hasura example for configuring NextAuth. This works by configuring your app with a protected API route that uses your Hasura app's ADMIN_SECRET to insert new users who have authenticated with a third-party.
If NextJS isn't an option, Hasura's Auth0 example similarly uses a callback method to insert an authenticated user if they don't exist.
In the user table, for the user role, you need to add a permission with custom check. And the check should be user_id equals x-hasura-user-id.
{"id":{"_eq":"x-hasura-user-id"}}
For non-logged-in users, leverage the anonymous role by setting the permissions that make sense for your use case: https://hasura.io/docs/1.0/graphql/manual/auth/authorization/common-roles-auth-examples.html#anonymous-not-logged-in-users
Edit after the comment:
Ah, I see. When the user comes to your app, your app goes and retrieves some data that it expects every user should have (for example perhaps the user info store on the user table). But since it's a new user, this info is not there.
At this point, your React app knows that:
there's someone with a legitimately signed JWT cookie (use a library to verify the signature) and
there's no user info from the backend. Therefore, the React app shows
a "Welcome new user, wait while we're setting up your account".
Then
the React app makes a mutation to a signup Hasura action you'll
prepare. Once that returns, you proceed as usually (redirect the user to their home page).
use hasura action handler instead. Inside your handler, do a check if the user already exists or not. If not then insert a new row.
Im doing claims based user role authentication. For this authentication i tested the following:
var identity = new ClaimsIdentity(new[] {
new Claim(ClaimTypes.Name, name),
new Claim(ClaimTypes.Email, email),
new Claim(ClaimTypes.StreetAddress, Address),
new Claim(ClaimTypes.Role, "Admin")
},
My authentication works just fine, but the i realized that i should implement some kind of security in order to avoid that the user can tamper the set role.
Therefore i stumbled across this, that is supposed to be added in the Global.asax:
AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.Email;
I can't seem to exactly understand what this code above does? Am i right, if i say that it gives the cookie, that the user holds, a unique token made from the email, that then is used to validate the legitimacy of the user by the system?
Im new to this, by the way, so go easy on me :-)
I'm not quite sure what you're meaning by your question, but let me try to clear out a few things.
First, let's talk about your AntiForgeryConfig line of code. What it does is configure the AntiForgeryToken to use the Email claim to identify the request (creates a token based on the email). The AntiForgeryToken allows you to trust a request and prevent Cross-Site Request Forgery (CSRF).
It is implemented in 2 parts. First you need to add the AntiForgeryToken to the form (#Html.AntiForgeryToken). Second, you need to validate the token in your controllers' actions (ValidateAntiForgeryTokenAttribute).
Here is a link to explain what CSRF
Here is a link with up to date code how to implement it
As a side note, you said ... to avoid that the user can tamper the set role. AntiForgeryToken doesn't do anything about tampering roles. Tampering roles would more related to your authentication process.
I am using auth0 for authentication. I want to fetch all users including their roles. I generated token in auth0 and when I try to execute it in Postman or fiddler tool, Sometimes it's giving roles and sometimes not. Same thing is happening in application also.
If I add manually in app metadata in role property as below, Then information is coming.
{
"authorization": {
"groups": [
"Admins",
"Users"
],
"roles": [
"Admin"
],
"permissions": []
}
}
But I fill, that if I change in authorization tab, It should effect here also.
Below is my code,
var apiUser = new ManagementApiClient("<<Token>>", new Uri("https://<<Domain>>/api/v2"));
IPagedList<User> allUsers = await apiUser.Users.GetAllAsync();
Do I need to clear cache in auth0, If yes then how?
Based on the information you provided it seems that you're using the Auth0 Authorization extension to configure user role information.
If this is the case you should notice that the extension logic is run at login time by the means of a rule. When you have that extension installed you should also have a companion rule; in my account the rule is named auth0-authz and should be the same for your case assuming version 2.0 of the extension.
The impact of this is that the roles are surfaced at the user level at login time, so any changes to the configured roles will be seen next time the user logins.
Note: Since this logic is part of a rule it will only be executed in the context of a login. If users are added to or removed from a group this will only be reflected within Auth0 after this user logs in again (eg: in the user's app_metadata or when calling the /userinfo endpoint).
You're querying the users directly through Auth0 Management API which may lead to the situation where the roles currently stored at the user profile are not up-to-date. If you are seeing stale information then this might be the cause.
On the other hand if your problem is not exactly this one, please provide further information and if possible steps to reproduce. For example, do the roles information show for one user but not the other or does it show for user A in one response, but then if you make another request the response does not include role information for that same user A?
I was not using the authorisation extension, but rather the standard role. So I've had to create the below rule.
More info here : http://isbyr.com/return-user-roles-in-auth0/
function (user, context, callback) {
// Get the user roles from the Authorization context
const assignedRoles = (context.authorization || {}).roles;
// Update the user object.
user.rolez = assignedRoles;
callback(null, user, context);```
Context:
I've implemented OpenIddict in my application, basing on GitHub readme. I currently use TokenEndpoint to log user in.
services.AddOpenIddict<ApplicationUser, UsersDbContext>().EnableTokenEndpoint("/api/Account/Login")
Although calling /api/Account/Info works and it returns token in response, I need to get some basic data about logged in user (username, email, account type). Response from token endpoint doesn't provide that.
I've found something like UserinfoEndpoint:
.EnableUserinfoEndpoint("/api/Account/Info")
But what I see after in http response is:
{
"sub": "ea2248b4-a[...]70757de60fd",
"iss": "http://localhost:59381/"
}
This should return me some Claims. As it doesn't return anything, I assume that no Identity Claims were created during token generation.
What I need to know in a nutshell:
Is using Token Endpoint correct way to log in user?
Do I need to generate Claims by myself?
Can I control Claims by myself and how?
How to make some Claims visible through UserInfoEndpoint?
Is using Token Endpoint correct way to log in user?
Yep.
Do I need to generate Claims by myself?
The userinfo endpoint simply exposes the tokens stored in the access token (which is something that may change in the future).
Can I control Claims by myself and how?
How to make some Claims visible through UserInfoEndpoint?
To allow the userinfo endpoint to return more claims, you'll have to request more scopes. Read http://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims for more information.
In a future version, we may allow you to return custom claims, but it's not currently supported.
ASP.NET 4.5 / C# / SQL 2012
I already have a well defined database with a users table and a roles/permissions column. The column contains a delimited list of roles. I was hoping to use ASP.NET's built in features on the back-end so I can be lazy and use things like the and filter by role. I'd like to read my roles from the database and tell ASP these are the roles my user is in. Custom...but hopefully simple. Here is what I have so far:
//create an identity
GenericIdentity objIdentity = new GenericIdentity("Matt"); //this would actually be the username/email of the newly authenticated user
//get roles for user
string[] strRoles = { "ADW", "USR" }; //this will get read from the database on authentication
//add identity and roles to a principal
GenericPrincipal objPrincipal = new GenericPrincipal(objIdentity, strRoles);
//add to current user
HttpContext.Current.User = objPrincipal;
//add the principal to the current context of the current thread
Thread.CurrentPrincipal = objPrincipal; //not sure what this does, doesn't affect my results/tests
If I execute the code above and then run the following:
Response.Write(User.IsInRole("ADW"));
Response.Write(User.IsInRole("xxx"));
I get a True/False as expected. However, this doesn't persist to the next page. I did a fair amount of reading on custom membership/role providers, but I can't find this specific use case. Most talk about setting up a DB specifically for this task. I also saw mention of the newer Simple Membership, but couldn't get any love from that end either. I'm hoping there is a solution that involves what I'm already doing. I'd love to execute this code when the user authenticates, but be able to reference this user in other pages. I could always call to the database for every page. I'm assuming that would suck, and that's not what the built in provider does.
Thanks all.
You are approaching it from the wrong side. You don't have to create identity and principal manually, assuming you are not creating a custom authentication module.
In any other case, you only choose the persistence mechanism and the corresponding authentication module sets the identity/principal according to the persistence.
A commonly used persistence mechanism is Forms Authentication, where you issue forms cookies. The forms authentication module makes sure the identity/principal is set early in the pipeline and takes the cookie as the source of information.
If you want to replace the cookie by your custom cookie (in other words - replace forms authentication with your own) - you have to think of a way to persist the security info, to the cookie for example.
Note, however, that this is probably not necessary. The very same forms authentication can be used with any custom membership and role providers. This is because these two have different responsibilities - membersip provider is for actual authentication whereas forms authentication module is for persisting the information for consecutive requests.
Edit: to add a role for a user so that it is persisted in the user database:
Roles.AddUsersToRoles( ... );
But first, you'd have to create users in the user database:
Membership.CreateUser( ... );
Note that Roles and Membership are facades for actual role and membership providers. While default providers use the membership database, you can easily create custom providers that persist the information anywhere at the server side.