Validate username/password against Azure AD without a UI? - .net-core

How can I validate a username/password against Azure AD without showing a UI? I have an autonomous processes running (think Windows Service or scheduled task) where the username and password are stored in a configuration table.
Since there is no "user at the wheel" so to speak, we can't use the normal method that shows the Azure login page (https://login.microsoftonline.com/{tenantId}).

1. Just make it work, no changes approach (Not Recommended)
You can try to get a token using Resource Owner Password Credentials Grant. (ROPC might be the least secure among all the different grants supported and brings potential attack risks. Also note that ROPC doesn't work with MFA and has issues with federated authentication users or may not work in those cases at all)
I don't think there is any method/endpoint available to specifically validate the username/password, but the workaround is if either username or password is incorrect, you will get an exception from the token endpoint when using ROPC, otherwise you get back a valid token which means credentials are good.
You can read about how to get a token using ROPC here:
Resource Owner Password Credentials Grant in Azure AD OAuth
2. Suggested Approach, some changes required (Recommended)
This might feel a little inconvenient at beginning, but it will be well worth the effort from a security standpoint. Note that this approach as well as the first one will meet your requirement of not going through normal login page as well.
Since there is no "user at the wheel" so to speak, we can't use the
normal method that shows the Azure login page
(https://login.microsoftonline.com/{tenantId}).
As you mention that the autonomous process is like a Windows Service or Scheduled task, from Azure AD and OAuth 2.0 perspective your process looks like a Daemon service. So instead of using a username/password credentials directly from configuration, which violates security best practices, you should be looking at using Client Credentials Grant. It's strongly advised NOT to collect/manage/store end user credentials (or create old world Service Accounts) directly in your applications.
You can read about it in detail here: OAuth 2.0 Client Credentials Grant with Azure AD.
Also visit this documentation for all Azure AD app types and scenarios, specifically those listed for Daemon apps. Link
To put it very briefly, your process gets represented by a registered application in Azure AD and for credentials part you can use:
a. Client ID + Client Secret Key (provided by Azure AD specifically for your application. you can generate more than one secret keys for different purposes with different expiration etc.). Sample C# code with Client Secret
b. Client ID + Certificate (pass a JWT that you need to create and sign with the certificate you registered as credentials for your application). Sample C# code with Certificate

Related

OAuth2 protected API. How to allow customer's to SSO using its own authorization server?

I have an Angular Single Page Application (SPA) talking to my ASP.NET API.
The API is protected by my own Oauth2 server (IdentityServer4).
One of my customers (let's call him X) wants SSO: Their users on my platform would sign in on their server instead of using the login form in my app that connects to my IdentityServer.
Each customer has its own subdomain for the Angular SPA (e.g. x.myapp.com). Therefore I can easily redirect X's users to their server's authorization page to approve my API, based on the hostname.
However the API itself uses one common hostname for all customers(api.myapp.com). Customers are distinguished by the Origin header of the API call (x.myapp.com) during the login call (and a few other unprotected calls) and by the Bearer token for protected calls to the API.
How does my API introspect the Bearer access token? Who should know which server to query ?
Is it the responsibility of the API server? Or can I tell my IdentityServer about X's oauth2 server ?
X's users would also be defined on my platform since we need specific info (such as config of roles on the platform). My current setup implies specific claims (such as user id) that allow my API to know what the user can do. Obviously, X's server will not provide the same claims. How can I connect the dots ? e.g. get some standard claim from X's server (username, email, whatever) and match it to my list of users.
Note: This question is similar but the answer is not accepted and seems to imply that the provider of both identity servers is the same (not the case here).
Formatting my comments as an answer:
From reading your question it's pretty much clear to me that you could benefit from what is know as Federated identity.
As you said, one of your customer want to achieve SSO - They want users to login using their existing accounts and be able to user your systems normally.
Since you already have an IdentityServer in your domain, what you can do is delegate the login part to the customer's side (whatever they do it). This is illustrated in the Identity server documentation Federation Gateway.
Basically, the approach is that upon hitting the "login" button in your front-end, you would redirect the users to your Identity Server passing some special params (prompt and acr_values for ex) which in turn, tells identity server to redirect the user's to the external Identity provider (the customer's). After a successful login, you have a chance in Identity Server to augment the claims, maybe using something they returned or anything really. Then the process is as normal - you return a JWT Token generated by your Identity Server
The benefit of doing this is:
Your SPA/API doesn't have to change. You will still work with your own bearer tokens and can continue doing authN/AuthZ as before.
You have a chance to add claims that might indicate where this user is coming from if needed
If your customer's server changes, you don't have to worry much, apart from maybe some tweaks related to returned claims
They don't necessarily need to use OpenId/OAuth on their side for this to work
Useful things you probably will need is some params to pass during the call to the authorize endpoint in Identity Server. (acr_values and prompt).
You can also check this in the quickstarts, by looking at Sign-in with external providers (which is pretty similar to what you want)
Now to your individual points:
Your Identity Server should be the "bridge" between you and the customer's "identity provider".
Upon a login from an external provider (X), you need to somehow identify the user on your platform. You could use email or, even better, if X is already using OpenId/OAuth they might give you the sub claim which is the user id on their side. At this point you need some sort of agreement with them otherwise this might be flaky/unreliable for both sides.
In a more "advanced note" you could also add to your tokens some sort of claim that tells you who is the source provider of this user. Here the source provider would be X. This is useful because you might want, for example, configure allowed identity providers in your app, or maybe enable features only for certain providers. Like, ppl logging in with Google might only see certain parts of the app.

OAuth2 - Authorize with no user interaction

So I'm trying to access my own data from an external app via their API. I only need access to my own data. Not trying to receive data from any of my users' accounts, so they don't need to authorize anything. So obviously I need to avoid any redirects (which seems to be the standard process the more I research OAuth...)
The process is hit the /authorize endpoint, which returns a code. Then provide that code in a request to the /token endpoint. Which then allows me to access my account via the API. I'm 95% sure this process is standard for all OAuth, but figured I'd provide details in case it's not.
How do I provide credentials on the back end to get a code to enter into the request for a token, so that all user interaction is negated? The API I'm using forces me to use OAuth.
The oauth2 grant you are describing is called Authorization Code Grant. This way of authentication has been designed so that applications which want to access resources of a user do not have access to the users credentials.
So if you found a way to interact with the user credentials in this grant it would be considered a hack.
If you do not want the individual user to enter the username and password but you want to access the api with a kind of "system account" this is not the oauth grant you should use.
There are multiple grants that would work for you. The question is which are supported by the authorization server and available to you.
Resource Owner Password Credentials Grant
This grant type is suitable for clients capable of obtaining the resource owner's credentials.
However
The resource owner password credentials grant type is suitable in
cases where the resource owner has a trust relationship with the
client, such as the device operating system or a highly privileged application.
It is very likely that this grant type is not avaiable as it could be misused to steal user credentials.
Client credential grant
The client can request an access token using only its client credentials.
How the resources are tied to a client is not part of the oauth specification and therefore provider specific.
If you want to read more about oauth2 here is a good article.
The Oauth 2 grant flow that you're describing is the Authorization Code Grant Flow, like NtFreX's answer says. And like they say, if you have the option of using one of the above two grants with that API, that's the easiest solution.
However, if you don't, there's still a way to avoid "user interaction". It's unclear what you mean by "user interaction", but in the Authorization Code flow, that usually means logging into a web app that calls the API you are trying to authenticate into, and then consenting on the consent page. See https://dev.fitbit.com/docs/oauth2/#authorization-page for an example (I implemented OAuth 2 for Fitbit :)). You'll need to use an automated web browser like Selenium to click the consent button. Then you can capture the code in the response from /authorize and send the code to the access token endpoint.

Authorization method for REST API utilising Active Directory

What is the best method of securing a REST Web API with the following requirements. The system has an Angular JS frontend with the REST APIs implemented in ASP.net.
There are two "roles" in the system, users will have one of the
roles. One role should allows access to some APIs (call it "VIEW"),
the other role allows access to other APIs
All users are in Active Directory, so if I have a username, I can check what role they are in- Some clients are on Windows boxes, the others are on Linux
I would like to persist the session so I don't have to look up AD for every API call
I would like single sign on. On the Windows machines, I don't require them to enter user and pass as I already can retrieve their username using Windows Authentication.
I believe that Oauth would be my best option.
There are two "roles" in the system, users will have one of the roles.
One role should allows access to some APIs (call it "VIEW"), the other
role allows access to other APIs
For role based authentication, you can use [Authorize("Role" = "Manager")]. The token will be provided by the identity server and will contain the claim as Role.
All users are in Active Directory, so if I have a username, I can
check what role they are in- Some clients are on Windows boxes, the
others are on Linux
If you have ADFS then you can have an Identity server that trusts the ADFS. The ADFS will provide a token which will have the claim for role and your Identity Server will do the claims transformation and will return the same Role claim back to angular app.
I would like to persist the session so I don't have to look up AD for
every API call
For this while requesting the token, you can ask for offline scope so the Identity server will provide the Refresh Token with Access Token so you don't need to ask for AD again and again.
I would like single sign on. On the Windows machines, I don't require
them to enter user and pass as I already can retrieve their username
using Windows Authentication.
For this one, you can have your Identity sever trust the WSFederation for windows Authentication.
So basically you need to setup Identity server that will provide you with the token and the REST API will use that token to verify claims to return the correct information back to the user.
I am not sure what you expect exactly. Anyway, first I'm gonna reformulate your question with requirements:
you accounts and role are in active directory
you want to manage roles based on an active directory group
you want anybody whatever the system (windows, linux, mac, mobile...) to connect on your application using the same authentication
you want to avoid your AD to be hit constantly (not at any call for example)
if the user is connected on an application that uses the authentication system, he doesn't have to do it so again on another application that uses the same authentication system
If these requirements are yours. I believe the only standard (and clean) solution is to use OAuth. I'm not gonna go in detailed description of OAuth, but this authentication protocol is the most standard one on the net (facebook, google, twitter...). Of course as you don't want to use facebook, google or twitter accounts in your business applications but your active directory accounts you'll have to install/setup/develop your OAuth identity provider using accounts of your active active directory server. Your choice will depend on how well you know ADFS protocol and its different flows (code, implicit, assersion) You have two solutions for it:
Use ADFS: install ADFS; it provides a OAuth portal that will work out of the box with asp.net mvc. This uses the code flow of OAuth that is the only OAuth flow supported by ADFS. For roles and its related AD groups, you'll have to map role claims with AD groups. (it's in the setup of adfs, you'll find many tutos on the net). You'll find lot of tutos as well about how to use ADFS with asp.net mvc/asp.net webapi. I mention .net here, but every technology has an implementation for OAuth authentication (nodeJs/express, php, java...).
Use thinktecture identity server (.net technology). This will provide all the foundation to implement a custom identity server with the least effort: http://www.thinktecture.com/identityserver / https://github.com/IdentityServer/IdentityServer3. It contains an addin to plug its accounts to active directory. With this, you can use implicit and assertion flows.
Use oauth2orize (for nodeJs): https://www.npmjs.com/package/oauth2orize. This will permit you to make the same than thinktecture identity server but in nodeJs. Apparently you'll have to make all the wirering with ad manually. With this, you can use implicit flows (not sure about assertion flows).
At application side, most of frameworks can authenticate easily using OAuth with a lot of existing frameworks. For example, even if you make a single page application, you can use adal.js or oidc.js for angular if you use angular. As I mentioned above, all this is taken in charge by asp.net mvc/webapi out of the box but I know it's the case for other server technologies. If you have more questions, don't hesitate as I'm not sure of what you expect exactly.

Headless authentication with Azure AD (user/pass combination)

I'm following the guide and example provided by Microsoft here and I'm able to get the demo working, with the authentication happening in a console app, then making a request to a Web API with the correct token.
I'm looking to use this but the code in the console app would need to move to a Web App. Essentially: external server tries to access secure Web API, providing Azure AD username/password in the Authentication header of a HTTPS request. I pick up these credentials in the first insecure Web API, and attempt to authenticate the credentials against AD, obtaining the token. From here, I would then call the [Authorize]-protected Web API by making a request with the AD token.
At this point I'm using the same code from the example linked above, simply moving the code in the Console app up into the first insecure Web API controller, but I'm having no luck. I read on CloudIdentity that "You can only use those flows from a native client. A confidential client, such as a web site, cannot use direct user credentials.". Is this true? If so, is there another way to achieve my aim? I need to use the credentials as it may be likely that more services would use the API in the future, so each of these would need their own credentials to use that could be managed within Azure.
EDIT: In reading more around this, should I actually be aiming to use Client authentication, creating an "Application" within the Azure AD, and providing the client ID to each external service looking to call the API, to then authenticate with that, rather than credentials?
Yes, your edit is correct. The Resource Owner Password Credentials grant is meant to authenticate users, not applications. Typical use would be from an application that prompts you for username and password and then retrieves a token from Azure AD.
You can use the Client Credentials grant to get a token from Azure AD from a confidential client to call an API without user context. This flow requires that you register the application in Azure AD and generate a key (which will be used as the client secret). You can then use the ADAL library to ge a token from AAD as shown here.

How to integrate AD authentication + SSO with exsisting Forms authenticated Saas web application

We are running a Saas ASP.NET 3.5 Web application using Forms authentication on a IIS 7.5 public server with protected content for thousands of users. We also have some subapplications running ASP.NET MVC 2.
Usernames and passwords are stored in our database and every user has roles and groups attached, with privileges and access rights defined.
Now we have been asked to also facilitate for simple SSO login via Active Directory so that users do not have to enter username and passwords twice to login. These users will originate from different networks and domains.
No user "sync" should take place from our servers to LDAP serves. We are not sure that any communication with LDAP is needed since all users will be created in our system and maintained there. Forms authentication will be used for most of our users.
From here on we are unsure which is the best path to choose. For our scenario what would be the "best practice" way to proceed?
The simple answer is SAML. It is considered the "best practice" and many large SAAS providers support it.
SAML protocol defines the single sign on flow between multiple systems. It establishes trust between systems using certificates. Your application accepts an assertion containing attributes (user id, name, email address, etc.) from other systems. Your app will map the user into your user store.
In .NET world there are several options. You can find a library that implements SAML (ComponentSpace has one) and hook it into ASP.NET authentication. You can create your own using Windows Identify Framework (WIF). Here's the boatload of WIF videos http://www.cloudidentity.com/blog/2010/06/23/ALL-WILL-BE-REVEALED-7-HOURS-RECORDINGS-FROM-THE-WIF-WORKSHOPS/. You can try IdentityServer http://thinktecture.github.io/
Depending on how secure your app must be, you can opt for a simple option of passing user id from trusted networks using a simplified method. I've seen apps that allow user id to be sent via URL parameter or form field. Of course, this is horribly insecure, and you are taking on more risk, because the trust between two networks is not cryptographically enforced. You can mitigate it somewhat by checking referrer string or IP address (if you can isolate IP range of a corporate network for example). But you are still open to spoofing because any user can impersonate others by simply replacing user id within HTTP request.
It probably doesn't answer your question fully, but hopefully points you in the right direction.
I recommend looking into ADFS 2.0 it is very powerful in terms of claims mapping and works with AD: http://msdn.microsoft.com/en-us/magazine/ee335705.aspx
What you would make is a token consuming portion of your app that would receive and parse the final claims returned to your web server after the authentication loop.

Resources