Single sign on with ADFS - c#

I am looking for single sign on for my application which is built on javascript (no server side language).
Requirement:
Agent log in to Windows (user integrated to Active directory)
Open my web page
Based on who logged in to windows, my application goes to AD and pull some user
specify data (eg email, phone)
How shall I go about it?
As per my understanding I will require ADFS for this.
So:
User goes to my web page
My web page calls some Web services or web application (which is build on c#)
That will authenticate against AD FS and get claim
Either get phone number and email in claim or get username and query AD for phone and email
Return the data to my web page (build on javascript)
It seems there something wrong in my understanding!!
Please suggest more appropriate solution based on my requirement

Frankly, I can't think of a way to make it work without a server side processing. This is because the ws-federation protocol ADFS uses is not just about returning claims.
It is about returing a SAML token. The token contains claims but what is most important about it is that it is signed using the XMLDsig. How are you going to validate the token is a first big question. But there are surely external libraries that allow that.
But then, such authentication can easily be bypassed by modifying scripts in the browser. This is because the ws-federation stops where you get the token and then it is up to you to exchange the token for the actual identity. And this won't work when processed only at the client side.

ADFS 3 does not support the OAuth2 implicit profile, which would be an option, but still you would need to verify the token on the server to avoid session fixation.
You can setup something like AuthorizationServer that supports Oauth2/OpenID Connect implicit profile
http://leastprivilege.com/2013/09/19/adding-oauth2-to-adfs-and-thus-bridging-the-gap-between-modern-applications-and-enterprise-back-ends/
Another option is to use something like Auth0 (Disclaimer: I work for Auth0) which also supports OAuth2/OpenID Connect implciit profile. In that case you wouldn't need ADFS, there is a connector/agent that you install on your network that does not require opening firewalls or anything and it supports implicit profile that is suited to JavaScript apps. This is an example of a single page app tutorial (if you create an account it will tailor the doc with your credentials):
https://docs.auth0.com/singlepageapp-tutorial

Related

Basic Angular SPA connected with .NET Web API - implement SSO

I Will try to describe this as detailed as possible.
For using the SPA, you need to be logged-in, every request is authenticated by JWT. Login is a simple form with Username and Password fields, which are sent to the server. On the server, there are two types of login (kinda) - AD and Password (determinated by the user type):
API check if username exists and determine its Type
a) if type is Password: Check if password matches the data in Database
b) if type is AD: verify password on the LDAP server
successful login returns generated JWT, which is used for all further requests.
This App is available all over the internet, not just inside the same network as the server.
I would like to have some kind of "automatic login" with Windows account (so you dont need to manually type the username/pass, but the SPA tries to login automatically when u open the Login page).
I tried many guides for something like this, but nothing seems to work properly.
I heard that Kerberos/Auth0 should do the work, but I dont know how to implement it. Also I would still need to get that JWT for further requests. Do I need some kind of Microsoft request? Azure? Anything else? (If is needed, I can create another IIS application just with Login controller).
I hope you understand what I mean, and will be able to help!
Most Modern Browsers speak SPNEGO
Simple and Protected GSSAPI Negotiation Mechanism (SPNEGO), often pronounced "spenay-go", is a GSSAPI "pseudo mechanism" used by client-server software to negotiate the choice of security technology.
It just so happens that one of those client-server security technologies it can speak is Kerberos. (Windows machines generally have kerberos availble by default.).
So to actually get .NET to use kerberos authentication you really need to enable delegation for IIS as that's what speaks to the browser.

In Azure Active Directory authentication why is authorisation code flow used

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.

How to obtain credentials for Http Basic Authentiction

I'm writing a C# application and need to scrape some information from an rss page that only offers Http Basic Authentication.
This seems to leave me with two choices
Ask the user to input their credentials into my app (which has trust issues as the app is then a potential middleman attacker?)
Get windows to insert the credentials on behalf of my app somehow (does this facility exist?)
All the examples I've seen on SO have the username/password hardcoded in the app or passed in as parameters from somewhere unspecified. My use-case is I'd like to give this app to people who may not want to trust it with their password.
How is this usually handled? Thanks
Short answer: It is not possible with basic auth. It is generally not possible with the OS a the trusted instance.
Long answer:
The proper way to solve this would involve a procedure where your application hands control to the OS (Windows), which then asks the user "Do you trust application XY to use your identity?". After user acceptance, your application would receive a security token which you could use afterwards to make your HTTP request to get the RSS feed. The problem is, that the site in question does only accept basic auth. This means, that the "security token" is the base64-encoded username and password. So the username and password would be exposed to your application anyway.
The second problem is that the OS and the RSS site have to share a secret (i.e. an encryption key not available to you or anyone else not allowed to log in site users), to enable the OS to issue a secure token that is trusted by the RSS site.
How the problem can actually be solved
The default, real-world example for the access of web resources with third-party software on behalf of the user without knowing his password is OAuth, see for example the Facebook login flow. (However, this requires the website/resource in question to provide third-party access. As your question indicates, this does not apply for your use case.)
The pattern employed is the following:
Prerequisite: You need to register your application with the RSS service provider to obtain an application ID and an application secret.
Your application redirects the user to the login endpoint of the identity provider.
The user accepts (or declines) the access of your application to his identity and data (e.g. the RSS stream).
The identity provider redirects to your app
Your application receives a token which can be used to make authenticated requests on behalf of the user. This may involve additional steps like exchanging the token for another.
Alternative Solution (does not answer your question):
Sometimes (protected) RSS feeds can be accessed via secret user-specific URLs. Of course, the user would have to provide your application with that url.

.NET MVC Authentication - Forms + Windows Authentication

I am currently working on a project that has a requirement that is causing me some issues and I want to know the best way of handling it.
Essentially we would like internal users to be able to access the MVC application and be authenticated through AD, this we want to be pretty much like SSO, they sign on to their computer navigate to the site and they are in.
The second type of users are outside partners that do not exist in our AD and we want to manage through our SQL Server. For these users we want to display a login page and do forms authentication.
My thoughts at first were simple, let IIS try and authenticate with windows authentication and if it fails (401) redirect to a login page. I don't currently have an environment to test this in but from my understanding in IIS7 it is not that simple and requires a little bit of a "hack" to accomplish. I need to avoid anything like that I need a solution that works as the system was designed to work and not by tricking it.
I have looked into ADFS and WIF but ADFS only supports AD not SQL and from what I've seen there is no STS that supports SQL Server. I have contemplated hosting both an internal application that used windows authentication and external application that used forms authentication but I want to avoid this if possible.
Ideally the flow that we want is user navigates to the MVC application IIS tries to do windows authentication, if it fails (401) redirect them to the login page. From there the login page will authenticate the user credentials against the SQL Database. What is the best way of accomplishing this all within 1 MVC application?
Thank you!
I would just implement my own authentication on top of FormsAuthentication or OWIN if you are using ASP.NET MVC 5. It is really simple and you will have full control over where you go to authenticate users. Trust me it isn't as scary as it sounds. I've written a few posts about it that you might find interesting.
MVC 5
http://www.khalidabuhakmeh.com/asp-net-mvc-5-authentication-breakdown-part-deux
MVC 4
http://tech.pro/tutorial/1216/implementing-custom-authentication-for-aspnet
I currently use the MVC 4 method to authenticate against an Active Directory domain with great success. The only thing I would recommend is you Cache your calls to Active Directory as it can be unreliable at times.
There is the STS that supports sql server, it is the IdentityServer.
https://github.com/thinktecture/Thinktecture.IdentityServer.v2
It even supports custom membership providers which give you quite a lot of different possibilities. I am not sure however if it supports automatic fallback to forms when integrated authentication fails. If not, there are two options: a custom sts or two explicit stses and an explicit choice for users. We have implemented the latter scenario once with ADFS - there were two adfses, one with Forms, the other one with integrated auth, first one federated with the other. This gives an explicit choice on the home realm discovery page - ".would you like to log in with username/password or try the integrated authentication"
You could create a project that uses "On-Premises Authentication" which uses ADFS to authenticate users. The on-premises authority URI will be:
https://yourADFSservername/federationmetadata/2007-06/federationmetadata.xml
After your project is loaded, you can to goto your ADFS settings and create a new "Relying Party Trust" and pass on HTTPS URL that your MVC app will be using. Setup to used LDAP attributes as claims and that will sort out AD authentication easily as it will navigate users to organisational sign-in page just like Office 365. Then if authentication fails for certain users, take the user to send the user to normal sign-in/signup page that exists independently of AD and connected to SQL server. You could skip windows authentication altogether by using on-premises authentication.

Single Sign on with 2 subdomains, one Java, one .NET

I'm currently looking for a nice solution for the problem above. We'll probably run form authentication on the .NET one.
I have an ASP.NET MVC app running on a.mydomain.com and a Java based app running on b.mydomain.com.
What is the best approach so that I don't have to log in to each app. Say, when I log into the a.mydomain.com and then open the Java b.mydomain.com, and it will check and see that I'm already logged in?
Would the WCF AuthenticationService class work for this? Could I do an AJAX request from the JavaScript of b.mydomain.com to check if I'm logged in already in the .NET app?
As long as mydomain.com is not in the public suffix list ( http://publicsuffix.org/list/ ), a.mydomain.com can put a domain cookie for .mydomain.com
( note that you can only go down one level in putting cookie : a.b.mydomain.com can not put a .mydomain.com cookie )
The cookie will be sent to b.mydomain.com (as well as *.mydomain.com and mydomain.com) and can be used as a token to open a session. So be sure to control the whole *.myDomain.com subdomain and make it httpOnly and secured (https)
Response.SetCookie(new HttpCookie("myCookieName", "myCookieValue") { HttpOnly = true, Domain = ".myDomain.com", Secure=true });
Some parts of the Atlassian Crowd solution http://www.atlassian.com/software/crowd/overview are based on this cookie mechanism
So you might :
Enable forms authentication on a.domain.com
upon successfull login build a myToken cookie which value contains userId and hashed userId with hashing key known by a.myDomain.com and b.myDomain.com
set the cookie with domain .myDomain.com
when user enters b.myDomain.com, check the cookie server side (in java) for matching between userId and hashed value
if the cookie is correct, open session for user userId
Note that you won't be able to access the cookie client side (so no js cookie handling, except if it is server side js, for example nodejs)
Using a Java or .NET existing solution is not likely to function on the other platform. You need several capabilities:
Tracking the client with an identifier for recognition (session, cookie).
Have both the Java and .NET application be able to get the related information.
How can you do these?
This is actually quite easy. You're using the same domain so you can place a cookie on the browser for all domains, meaning that requests to a* and b* will both have the cookie sent to the server. Both Java and .NET have excellent facilities for cookie placement.
This is dependent on your back-end. What are the systems using for persistent storage? If you have something like a MySQL database which both systems are connected to, you can make a table with login information for each stored identifier for authentication. If you take this route, have some sort of time-out as well to invalidate old authentications.
If you have both those pieces of information, you can do the authentication on each system.
I recommend using one of enterprise sso protocols, Oauth2 or ws-federation. This gives you maximum flexibility in composing your services, you can not only federate these two but then, later, easily expand your application environment. Both protocols do not need apps to be on the same domain.
Although this could sound overcomplicated for your simple needs, you do it once and have the sso problem solved forever, no matter what happens in future to your applications.

Categories