When returning from Azure ACS I retrieve a federation authentication result inside a FormCollection. The value containing the information I need is inside an encrypted value called "wresult". I'm having problems decrypting this value to use it for further authentication.
I don't want to use the WSFederationAuthenticationModule because I don't authorization cookies to be set. When the module is used, it'll automatically set auth-cookies with the Federated-Authenticationtype.
I instead want to retrieve the claims contained in the wresult and then set my own security token (be it JWT, SAML 2.0 or whatever).
The only possible workaround I found so far is to use the FAModule, and then delete the session token cookie right away. But this will result in the auth-cookies to be set twice in the response, with the value and right away unsetting it.
What I want to achieve in the end is the following:
Providing the possibility to either authenticate with a forms site, or authenticate using any identity provider in Azure ACS. Using the forms authentication I can compare the username and password right away and set the security token with whatever claims I want it to have. But when using Azure ACS, I want to compare the retrieve nameidentifier with saved values in my database first, and then set my custom security token, instead of the WS federation one. Or in case the nameidentifier is unknown, I want to redirect to a forms page where the user can authenticate this nameidentifier with his credentials. I don't want the azure ACS returned value to be calculated as authenticated.
You don't have to register the FAM - but you can still use its helper methods (e.g. GetSignInResponseMessage()) to parse the sign-in response message from ACS.
This gives you access to the protocol details and the returned security token without having to use the WIF cookie system.
Instead of modifying WSFederatedAuthenticationModule's default handling of cookies, I would suggest an alternative setup:
Create and host your own forms based auth identity provider STS. There are some nice options to help set this up.
Configure your new IP STS in ACS
Use the default ACS login page (home realm discovery page) or customize your own.
Now your users will get asked to choose which identity provider they want to authenticate with. If they choose yours, upon entering a username/password, your IP will send a nameidentifier to ACS, which in turn sends it to your relying party website. Same goes if you add google as an identity provider. The benefit is your RP doesn't need to behave differently depending on what IP the user logged in from, but if you want to customize some behavior based on the IP, that information is available in the token issued by ACS.
Also, if you want to use JWT tokens instead of SAML, you can configure ACS to issue them from your relying party page in the ACS portal (though this is marked as beta functionality).
Related
I have an duende identityserver that has multiple BFFs as a client.
One of these BFFs is for my admins.
My identityserver has multiple sign in schemes (Think facebook, google etc) however i want to force my Administrator bff to use the (Azure AD (for my organization only) login.
I was thinking maybe setting clientproperties in the database and having the identityserver respond to that. But i was wondering if there is a more standard way of doing it that I haven't thought about.
Some authorization servers have allowed authenticator settings, though others do not. I could not see a built in option in the client model.
Another option is for the client application (your BFF) to send the acr_values OpenID Connect request parameter to force that app to bypass authentication selection screens.
This feels like the preferred option in your case. After login your BFF could even validate the acr claim to check that the expected authentication method(s) was used.
Fun fact:
Duende identityserver has Client.IdentityProviderRestrictions
this is excactly what i needed for my goal
I am working on a .net MVC and web API project and using active directory to authenticate users to API, on authentication, a code is being returned from AD and I have to exchange the code to obtain a token and use that token to call the API, the question is why is the code returned and why do I have to exchange it for the token? can I directly obtain a token?
This is all because of security reasons.
OAuth 2.0 wanted to meet these two criteria:
All developers will not have an SSL enabled server and you should allow them to use non-HTTPS redirect URI
You don't want hackers to be able to steal access/refresh tokens by intercepting requests.
Since the Authorization Code grant has the extra step of exchanging the authorization code for the access token, it provides an additional layer of security not present in the Implicit grant type.
According to Nate Barbettini we want the extra step of exchanging the authentication code for the access token, because the authentication code can be used in the front channel (less secure), and the access token can be used in the back channel (more secure).
Thus, the security benefit is that the access token isn't exposed to the browser, and thus cannot be intercepted/grabbed from a browser. We trust the web server more, which communicates via back channels. The access token, which is secret, can then remain on the web server, and not be exposed to the browser (i.e. front channels).
For more information, watch this fantastic video:
OAuth 2.0 and OpenID Connect (in plain English) https://youtu.be/996OiexHze0?t=26m30s (Start 26 mins)
Your question isn't really specific to Azure AD, and is more about the OAuth flow and why it is used.
The flow seems a bit complex, and well, it is, but there are reasons for all the things it does.
I encourage you to use authorization code flow instead of other approaches.
It has many advantages:
Your app will never see the user's password
The user cannot see your app's client secret
The user cannot see your app's access tokens (and neither can a man-in-the-middle attacker)
You get a refresh token that you can use to get new tokens whenever needed (you do need to specify the offline_access scope for this though)
The user can go through multi-factor authentication, federated authentication with ADFS etc., and your app doesn't need to care about that
Alternative flows and their downsides:
Implicit flow
Gives you a token directly without the code exchange
There is no refresh token
Mainly used in Single Page Apps, where refresh is done using a hidden iframe, but that depends on the user's session remaining active
If you use this outside a SPA, you can't really refresh the token, requiring the user to login again every hour
User can see and take your app's access tokens
Client credentials flow
Instead of accessing the API as a user, you access it as the app itself
Some APIs do not support this approach and require you to make calls on behalf of a user
This doesn't allow you to authenticate a user
Application permissions are needed to use this flow, which usually give very broad access to the entire organization
The upside of this flow is that it is very simple
Resource Owner Password Credentials flow
Do not use this flow
HTTP request to token endpoint with app + user credentials
Exposes user password to your app (!)
Does not work if user has MFA, expired password etc.
I have searched all over for an answer to this, and not found anything that seems to answer my question. Which feels like it should be an easy one (but clearly isn't).
I have an API which authenticates using a token. This token I generate from my application - more specifically, I have a new Token Generation web call that will return a token. Currently, I pass in a cookie with the user and password information, and it uses this to identify who I am and what I should be allowed to do. This is all working absolutely fine and hunky-dory.
I am achieving this process by making the Token Generation use OWIN Cookie Authentication, which means that the cookie is read and the Identity is set. I am then able to use this identity to confirm whether the user is allowed to access the system.
What I now want to do is replace this Cookie Authentication process by authenticating against a Windows User (everything is windows based, and this will be an option so non-windows users can still use the cookie authentication route). But I cannot discover how to straightforwardly do this.
Note that I don't actually need to validate that the user is genuine or refer back to the AD at all. If you provide a windows user that matches a user in the system, you can log in.
So how can I - easily - get the requesting user into the Identity Name? Or is this not possible?
If you are looking for information on the current user accessing your program, assuming the program is running on the user's machine and is windows based, you can simply query windows for the user's username or any other publicly available information about the user.
Refer to https://learn.microsoft.com/en-us/dotnet/api/system.environment?view=netframework-4.8 for information on the Enviroment class and what it's features are.
If you could provide some code or further clarity I could help you further.
I developed a Web API that uses token based authentication (using Identity and OWIN).
What I need to do is to identify the user in each request made with the token so that I can provide the data that only belongs to that user.
My idea is to insert / update that user record with the token right after the successfull authentication.
How can I do that?
I mean, how can I grab the token before returning the response to the client?
Or... is there any other way to accomplish that?
You don't need to store the token to identify the user. The user identity is self-contained in the token.
When the resource server gets the request OAuth2.0 middleware (implemented in Microsoft.Owin.Security.OAuth dll) decrypts the token and set it into the Identity property (context.Ticket.Identity or context.Identity in most of methods). Then you can check for the user identity.
Take into account that the authorisation server and the resource server can be separated and the resource server normally don't have access to the authorisation server database.
After I redirect to the OAuth dialog page, is there a way to authorize use of my account programmatically? Right now, once I enter my username and password, I can get the authorization code and the rest of my app works perfectly, but I want it to automatically authorize use of my account.
Edit: the user will never see any of the account information of course, but according to the api, in order to get the authorization code you need to authorize the account
The OAuth system is designed so that you cannot log in programmatically, you must display the dialog box to the user for them to log in to SurveyMonkey. However, once a user has logged in once you can then store the access token returned by /oauth/token, and use that to access a user's data whenever you need to.
If all you need to do with your application is access your own data, just store that single access token. When you retrieve it, it is returned in a JSON blob that also defines its expiry - currently SurveyMonkey tokens do not have an expiry (unless a user revokes the access token), so until that changes you can use this access token for as long as you require.
I would suggest checking out the SurveyMonkey OAuth guide for more information: https://developer.surveymonkey.com/mashery/guide_oauth