I just received an .Net API that uses Identity server for Authentication. I have never used Identity server before. So I'm lost looking for info.
Here is my code for authentication.
[HttpPost]
public async Task<IHttpActionResult> Post([FromBody] Login loginInfo)
{
OperationResult<string> result = new OperationResult<string>();
result = await GetAuth(loginInfo);
return Ok(result);
}
private async Task<TokenResponse> GetAuth(Login loginInfo)
{
var client = new TokenClient(Constants.IdSrvToken, Constants.ClientId, Constants.ClientSecret);
return await client.RequestResourceOwnerPasswordAsync(loginInfo.Usuario, loginInfo.Password, Constants.Scope);
}
This works ok. But I need to create a new API method that receives the current and a new password and change it. The TokenClient class doesn't have any useful methods that I can use, and can't find information related to how implent the password change.
Any suggestions where I can find info?
Thanks in advance.
There will not be one. The whole point of using Identity Server - and other providers like it - is to delegate responsibility for authentication to it, primarily so that apps and APIs have no visibility of user credentials. IS also has very little awareness of "users"; they’re just an abstract concept to it. Something like ASP.NET Identity is more focused on users.
Using resource-owner flow is quite counter to the whole intent of OAuth2, and should not be used in virtually all circumstances. If you’re using IS just for that, adding it to the equation is largely pointless. It doesn’t solve most of the problems OAuth2 was designed to solve, and you also get no Single Sign On.
In practice usually you would have web pages on (or alongside, on the same server) IS that provide the password change functionality, and you would give users a link or redirect them to those pages. I suspect most people using IS who want to manage users either integrate something like ASP.NET Identity or add their own pages. There are many articles written on the former; here is one as a starting point. It’s not exactly trivial but quite doable.
If what you have is a legacy app that is unlikely to migrate to using OAuth2 as intended, then ultimately your code just needs to change the stored password (or hash as it hopefully is) wherever the users are stored; e.g. a database table somewhere. IS won’t help with that though; you need to write your own code for that.
Related
I am new to blazor and stumbled across a problem when trying to implement authentication in my app. For now, I need to store all my users' data in JSON file and do not have a SQL DB to refer to, which, as I understand is needed to implement authentication.
As for now I have a list of users and check if the user is in my list of signed in accounts, then call markAsAuthenticated
public void markUserAsAuthenticated(string emailAddress)
{
var identity = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name, emailAddress),
}, "someType");
var user = new ClaimsPrincipal(identity);
NotifyAuthenticationStateChanged (Task.FromResult(new AuthenticationState(user)));
}
I would like to add roles or claims now to be able to include them in the component, but find it difficult to understand, what the following steps should be.
Most of the tutorials use Authorization services provided by VisualStudio, but we work in VSCode and I would like to implement this myself, so I can use the list of users I have.
I would also like to find out if I can use cookies or JWT in my app and if there are any good tutorials for that or suggestions considering work with VSCode and server-side work, thanks in advance!
If you want to use cookies you need to use a razor page (.cshtml). You can have a razor page inside a Blazor application. It's the same code you'd use in a traditional razor application (pre-Blazor).
There's nothing Visual Studio specific to this that I know of.
See https://blazorhelpwebsite.com/ViewBlogPost/36
I am building an API which will use authentication with Auth0 and will have web and mobile clients.
Both clients will get their tokens using web based login from Auth0.
I am looking for the best way to get and store some user information in my API database, so I can e.g. list users in some group, relate article with the author, give some permissions to the user which cannot be stored in Auth0 (for 2 reasons: no mtm tokens and more important, that it's sort of multi tenant app and permissions are to complex to keep them in tokens).
There is userId in the token which can be used but e.g. when to trigger user save/update? Running it on each and every request does not sound efficient.
Anyone has done something like this?
How to approach it in the best way?
I have figured out a solution, however if anyone here would recommend a better approach, please do! Thanks to comments I went into hooks and then rules direction, so I appreciate any engagement.
I see it as fairly simple case, a bit tricky during local development but can be worked around with some development middleware in the API.
I am going to use Auth0 rules with crazy simple rule:
function (user, context, callback) {
const axios = require('axios');
axios.post('https://my-web-api.com/auth0/notify', { user }, {
headers: {
'x-api-key': configuration.API_KEY
}})
.then(() => callback(null, user, context));
}
In the Rules, I have added API_KEY as a variable so it is not there in the code, encrypted, safe.
By using this I will send the current user profile from Auth0 to the backend where I will simply check if the user exists or not and update a profile if necessary.
As per docs:
Please note that rules also run during the token refresh flow.
it gives me also updates during the refreshing flow, so if anything changes, I will get the updates as well.
I'm looking to understand the nitty gritty mechanics of authorization so I can devise a strategy for my situation.
My situation is that I am part of a distributed application. My part is an MVC5 application that basically just consists of a couple of controllers that return single page app views. So hit controller A and get back single page app A. Hit controller B and get single page app B. Etc. This application contains no database or user data. Some other application on a completely different website/server does. I want to ask that other application if a user is valid or have users ask the other application directly themselves and only allow access to my app views if the answer is yes. So, in essence, I want to protect my controllers based on the word of a remote application that contains an exposed api for login/user validation.
It has been suggested to me that token authentication is the way to go. It's a bit daunting with my lack of experience with it, but I've buried myself in some reading and video presentations. Here is my current, weak attempt at summarizing the task based on limited understanding. Please correct as needed:
An access token needs to be generated
Getting an access token is not part of the Account controller, it's part of OWIN middleware
The access token will be sent along with the requests for my contoller actions
My controller actions, decorated with the [Authorize] attribute, will parse the token and do the right thing
Questions:
Q1: Should I generate the token or should the other app - the one with the db and user data?
Q2: My controllers don't know anything about users. That data is in the other app. What specifically are the controllers parsing for under the hood in order to do the right thing? In essence, what specifically tells them, "yes, this request is OK. Return the view."
Q3: I started my project awhile back using a standard MVC5 project template that comes with VS2015 because I figured I'd be handling users/login etc. That turned out not to be the case. Am I going to have to go back and redo this project from scratch because that template doesn't fit this requirement or can I do some surgery on it and continue? For instance, I don't know if that template has all the OWIN stuff I need or maybe has too much extra junk (bloated Account controller, Entity Framework, etc.) to be easily transformed/maintained.
Q4: Is token authorization overkill here? Is there an easier way to keep unauthorized users from accessing my controller actions that makes more sense given the nature of the project?
Any insight would be appreciated.
Update: What I meant in Q2 was, at it's simplest, how does [Authorize] work? Details? I'm guessing I have to tell it how to work. For instance, a silly example to illustrate. If I wanted to tell a controller decorated with [Authorize] to let anyone in who has the username "fred", how and where would I do that? I'm not so much looking for code. I'm thinking conceptually. My app must know something about the tokens the other app (authenticating app) is genenerating. In general terms, what would I add to my MVC app to tell it how to decode those tokens? Where do I add it? Is there one standard place?
I think you are on the right track and are right about the steps you have mentioned. I will answer your questions based on what I understand:
Q1. The other application is the one that needs to authorize and generate a token (whatever be the authorization mechanism they use) and you should receive this token before showing your views. Since the data is coming from the other application , they have to give your controllers access to their data. This is why you need to ask the other application for the token/authorization. With a valid token got from the other application your application can send valid and authorized requests to their data.
Q2. What you can do from your side is to add a check as to whether the request for your action/view is coming from an authorized user. For this, you need to check if this request has a valid token.
Q3. I don't know what you mean by "template" here. But if you need to integrate your controllers to the other solution, you do need to know what the other solution does and what it offers in terns of authorization and of course the data. They should provide your application access to a public api for this purpose.
q4. THis is something the other application needs to do. From what I understand, I think you are only adding a web API to an existing system so I think you need to really know how you can integrate with the other application. They should have clear APIs that are public for you to do this to access their features and data.
Since you have not mentioned if this other application is something like a secure enterprise solution or a Google API (has public API ) it would be difficult to tell exactly what you can expect from the other application.
I think you would need to try JSON web tokens (JWT )
I have not used it myself though . stormpath.com/blog/token-auth-spa –
It is useful for authenticating if a request to your controller. Here is a similar question as you have (I think) and how JWT could solve it How to use JWT in MVC application for authentication and authorization? and https://www.codeproject.com/Articles/876870/Implement-OAuth-JSON-Web-Tokens-Authentication-in
You can override the AuthorizeAttribute like this : https://msdn.microsoft.com/en-us/library/ee707357(v=vs.91).aspx . Your authorization logic of checking for whichever tokens/auth mechanism you decide to can be added to this new action filter. Then add that new attribute to your actions. So if your custom authorization attribute when overriding looks like this:
public class RestrictAccessToAssignedManagers : AuthorizationAttribute
Then your action would have the attribute decoration like this:
[RestrictAccessToAssignedManagers]
public ActionResult ShowallAssignees(int id)
Found a good article which could also be of help - https://blogs.msdn.microsoft.com/martinkearn/2015/03/25/securing-and-securely-calling-web-api-and-authorize/
My answer to your question will be based on:
I want to ask that other application if a user is valid or have users
ask the other application directly themselves and only allow access to
my app views if the answer is yes. So, in essence, I want to protect
my controllers based on the word of a remote application that contains
an exposed api for login/user validation.
Yes, to my humble opinion, oauth token-based approach is overkill for your need. Sometimes, keeping things simple (and stupid?) is best.
Since you are part of a distributed application, I suppose you can (literally) talk to the team in charge of the "other application/website" where requests that hit your controllers will be coming from.
So, I will skip your questions 1, 2, 3 and 4, which are oriented towards the token-based oauth approach, and suggest a rather different, "simplistic" and faster approach, which is the following:
For clarity purpose, let's call the other application "RemoteApp", and your application "MyApp", or "The other team" and "You", respectively.
-Step 1: You (MyApp) exchange a symmetric secret key with the other team (RemoteApp);
-Step 2: MyApp and RemoteApp agree on the algorithm that will be used to hash data that will be posted to MyApp when a user from RemoteApp requests a page on MyApp. Here, you can, for instance, use MD5 or SHA256 algorithms, which are well documented in MSDN and pretty easy to implement in C#;
Step 3: MyApp tells RemoteApp what its needs to be part of the posted data to validate/authenticate the request.
Here is an example:
Step 1: BSRabEhs54H12Czrq5Mn= (just a random secret key. You can choose/create your own);
Step 2: MD5 (this is the algorithm chosen by the 2 parties)
Step 3: The posted request data could include (at least 3 - 4 parameters or form fields, plus the checksum):
- UserName+RemoteApp fully-qualified domain name + someOther blabla data1 + someOther blabla data2 + checksum
The above information will be concatenated, without space. For instance, let's assume:
UserName = fanthom
RemoteApp fully-qualified domain name = www.remote.com
someOther blabla data1 = myControllerName
someOther blabla data2 = myActionName
The checksum will be generated as follows (function prototype):
generateMD5(string input, string secretKey)
which will be called with the following arguments:
string checkSum = generateMD5("fanthomwww.remote.commyControllerNamemyActionName", "BSRabEhs54H12Czrq5Mn=")
Notice that in the first argument the above 4 parameters have been concatenated, without space, and the second argument is the secret symmetric key.
the above will yield (actual md5 checksum):
checkSum = "ab84234a75430176cd6252d8e5d58137"
Then, RemoteApp will simply have to include the checkSum as an additional parameter or form field.
Finally, upon receiving a request, MyApp will simply have to do the same operation and verify the checkSum. That is, concatenate Request.Form["UserName"]+Request.Form["RemoteApp fully-qualified domain name"]+["someOther blabla data1"]+["someOther blabla data2"],
then use the md5 function with the secret key to verify if the obtained checksum matches the one sent in the request coming from RemoteApp.
If the two match, then the request is authentic. Otherwise, reject the request!
That'all Folks!
I seems you need to implement an OpenID/OAuth2 process.
This way, your apps will be able to utilise single-sign-on (SSO) for all your apps, and all you would have to do is set up your MVC5 app as an OpenID/OAuth2 client.
Take a look into Azure AD B2C which is perfectfor this (I am currently implementing this right now for 3 projects I am working on).
https://www.asp.net/mvc/overview/security/create-an-aspnet-mvc-5-app-with-facebook-and-google-oauth2-and-openid-sign-on
https://azure.microsoft.com/en-us/services/active-directory-b2c/
https://identityserver.io/
So your app is publicly addressable? I can't tell for sure from your description.
Well you only have these issues if a public client is requesting certain page views from you...
Now here's where i'm confused. If it's an external client accessing different parts of your distributed app, ALL the parts have this problem.
Generally the client authenticates itself at one place (say written by Team A), any other subsequent view requests would need to be checked as well (HTTP being connectionless/stateless), including others done by Team A? So your problem would already be solved (because it would be a problem for everyone, and they would have done something using an auth cookie + checking service, use the same checking service...)?
Which leads me to believe that the view requests are internal and not client facing, in which case... why is auth such a big deal?
If you could clarify your scenario around what requests you need to authenticate...
you are on right track. But instead of you implementing OAUTH and OpenIDConnect user third party which does the heavy lifting. One such tool is IdentityServer
https://identityserver.github.io/Documentation/docsv2/
Now answering your question from IdentityServer point of view
An access token needs to be generated -- true
Getting an access token is not part of the Account controller, it's part of OWIN middleware -- yes, for better design
The access token will be sent along with the requests for my contoller actions
My controller actions, decorated with the [Authorize] attribute, will parse the token and do the right thing -- Yes as a part of response header
Questions:
Q1: Should I generate the token or should the other app - the one with the db and user data? The identity server will generate token that you requested.
Q2: My controllers don't know anything about users. That data is in the other app. What specifically are the controllers parsing for under the hood in order to do the right thing? In essence, what specifically tells them, "yes, this request is OK. Return the view. - usually the token is sent back to the identtyServer to check for validity and to get access_token which will check if the user has access rights. if not [Authorize] attribute will throw error message and return
Q3: I started my project awhile back using a standard MVC5 project template that comes with VS2015 because I figured I'd be handling users/login etc. That turned out not to be the case. Am I going to have to go back and redo this project from scratch because that template doesn't fit this requirement or can I do some surgery on it and continue? For instance, I don't know if that template has all the OWIN stuff I need or maybe has too much extra junk (bloated Account controller, Entity Framework, etc.) to be easily transformed/maintained. - Yes u can delete the extra stuffs
Q4: Is token authorization overkill here? Is there an easier way to keep unauthorized users from accessing my controller actions that makes more sense given the nature of the project? -- It is not an over kill. It is the right thing to do for your scenario
I'm still trying to tinker around with the new ASP.NET Core MVC6 (former vNext). This time I tried to implement my authentication against an Active Directory instead of an Entity-Framework Database.
Since I found so little Documentation, I took the very well done ASP.NET-Template and started to alter it for my needs.
I also use ReSharper to decompile the Parts, since I'm really interested in the Details.
To not go too much into the details, I'm a bit worried I'm doing not the stuff Microsoft intended:
I left the SignInManager as it is and removed the UserManager, since
return await _signInManager.PasswordSignInAsync(model.UserName, model.Password, false, false);
Internally calls the UserManager. Now it gets quite tricky: To provide an alternative store to Entity Framework I need to implement
IUserPasswordStore<ApplicationUser>
Which has around 15 Methods, most of them seem never to get called for my simple Login-Check.
Furthermore, I also need to implement
IRoleStore<IdentityRole>
Which has another 10 Methods, although I don't even want Role-base Security at the moment!
Furthermore, the Verification of the Password does require a Hash, here is the decompiled Method:
protected virtual async Task<PasswordVerificationResult> VerifyPasswordAsync(IUserPasswordStore<TUser> store, TUser user, string password)
{
string hashedPassword = (string) await store.GetPasswordHashAsync(user, this.CancellationToken);
return hashedPassword != null ? this.PasswordHasher.VerifyHashedPassword(user, hashedPassword, password) : PasswordVerificationResult.Failed;
}
According to other SO-Threads, there is no way to get the Password of the AD, so I can't implement that properly as well.
I think the way to go would be to overwrite the SignInManager as well, but this seems to get quite a huge amount of Code, the most not even needed. Also the 2 Store-Interfaces seem to hurt SOLID quite alot, since the interfaces are so big.
Am I dong there something fundamentally wrong?
The reason we don't provide an AD version is security.
By implementing one you either now have an AD open to brute force attacks, because you're not disabling accounts (as that could take admin rights, and no-one should run their web app as a domain admin), or you do disable accounts and now, with a few requests I can lock out your users out of AD, which not only affects your web app, but their desktop computers.
Now add on top that in case of a breach I am now authenticated to your AD and, well, that will make attackers happy, but not your network admins.
As an aside, the password check doesn't need hashed passwords, simply authenticate against AD inside VerifyPasswordAsync and return the appropriate result.
My recommendation is either you look at integrated authentication if you are running in an intranet only environment, or Windows Azure AD if you are wanting to run in the cloud. Both of those are markedly more secure than attempting to leverage AD into an HTML forms based scheme.
I have a ASP.NET MVC site with a CAS server set up as the authentication type. I also have a separate database with a Users table and a Roles table (with a User being related to one or more roles). A User is only able to log into the system if the Username is both in the User table and on the CAS system. I have this solution working.
My problem is i now need some form of trigger on User.IsAuthenticated so i can track the current User (from my database), without the possibility that i am trying to allow tracking of a User that has logged out. What I've been thinking is i need to add the User to the HttpContext but i am not sure how to trigger the clearing of the User if the CAS session times out or if the User Logs out.
I also wish to have some functionality such as User.IsInRole (again using my database, not ASP.NET) but am not sure how to go about implementing this. I suppose if i can successfully add the User to the HttpContext then a IsInRole method would simply be a User.Roles.Contains(string role) method but how can that then be used if i wish, for example, to use a method with the DataAnnotation [Authorize(role = "ExampleRole")].
I have looked at questions such as How do I create a custom membership provider for ASP.NET MVC 2? but this doesn't work for me (possibly to do with me using the CAS authentication?)
Any guidance or background reading would be appreciated as i'm really not sure where i should even start. I have read up on GenericPrinciple, IPrinciple and IIdentity but I'm struggling to see how i can apply them to my current project.
Ended up with a custom Authorise Attribute that uses the CAS logon to check the user exists in my database. It also checks the roles of that user. I also used a static class to save the current user in the session with a logout method that abandons the session when the user logs out.
I have kind of a two parter for you. This link does a really good job of explaining how to replace the HttpContext User with your own object: http://bradygaster.com/custom-authentication-with-mvc-3.0
His approach uses MVC filters, but you can also catch the Authentication event in the Global.asax file. Using the forms system with your own implementation can be trivial or not depending on what you're doing, but it boils down to calling FormsAuthentication.SetAuthCookie and .SignOut, amidst your own logic.
public static void FormsLogin(this User user, bool persist)
{
FormsAuthentication.SetAuthCookie(user.DisplayName, persist);
user.AddHistory("Login event.", HistoryType.Login, "SYSTEM");
Users.OnUserLogin(user);
SetLastActivity(user);
}
public static void FormsLogout(this User user)
{
FormsAuthentication.SignOut();
}
Lastly, once you've got the login stuff working out, you can use your own more complex permission system by making a custom Auth Attribute. I remember piecing this together from some other answers and articles but I can't seem to find the sources at the moment, I will try and edit with sources for credit where it's due, if I find them. For now, all I can offer is this gist which offers up one of the attributes I use: https://gist.github.com/1959509
Keep in mind the only really relevant part there is the override of OnAuthorization, which does the actual work.