Is it possible to create an Azure Function which will take username and password as input parameters and function should validate user against Azure AD.
Firstly, it's important to mention that collecting username and password for an Azure AD user as part of your application (Azure function or web app any other application you're developing) is very much against the best practices and opens up multiple attack risks. So even though you may be able to use workarounds to achieve it, please do reconsider the requirement that you have from a security standpoint.
Workaround - ROPC - Resource Owner Password Credentials Grant (Not recommended, multiple issues)
Azure AD does not provide a direct API to validate user credentials. As a workaround (and a bad one at that), you can use Resource Owner Password Credentials (ROPC) flow which works with username and password to acquire a token.
It violates security best practices and also does not work with MFA and federated authentication users. Using this grant is highly discouraged as it brings potential attack risks, so not recommended.
If either username or password is incorrect, you will get an exception, otherwise you get back a valid token which means credentials are good.
Here are a couple of links that cover details on ROPC (and recommend not using it at the same time..):
ADAL.NET library documentation on acquiring tokens with username and password
Resource Owner Password Credentials Grant in Azure AD OAuth
For example, code would look like this for a native application.
result = await context.AcquireTokenAsync(resource, clientId, new UserPasswordCredential("john#contoso.com", johnsPassword));
Other references
Here is an old article but still very detailed. And look at the long list of limitations at the end.
Related
We currently have an Identity server 4 application. Using entity framework core and asp .net identity.
We have a group of supporters who need to be able to access our users accounts in order to help them with issues over the phone. Our users are not able to figure out how to use team viewer. As most of them are mobile and will only have a cellphone at the time.
I know all the security ramifications of allowing other people to sign into your account however there is really no way around this. Our customers have accepted that our supporters can connect to their account when they request it. We trust that our supporters only do this when its requested.
Current solution and its issues
The current hack creates an api endpoint which only our supporters can use as it has been locked down so that only those with supporter permission can use it. They send the users email and we hack create them an access token which is then used by the application (Web version) to act like its the user who is having issues.
This solution was created by my predecessor basically by taking the supporters access token and replacing all of the claims with this supporters id to the users id and returning it to the application. I hate this solution on a number of levels and its very unstable every time i look at this method it breaks. currently its not working because audience clams are incorrect for some reason.
What i want to do
I would really like to do this in a less hack way. So is there a way to sign in a user to the application without it actually being them thats doing the signing in and return an access token?
I have tried doing
await _signInManager.SignInAsync(user, false, null);
But i cant seam to figure out how to get that to return an access token.
What i would really like to do is have the ability for supporters to login to any ones account but do it securely somehow.
The problem with the user account is that it's not bound to one application. So by allowing others to login using the account, you give them also access to other applications. As a workaround you could use 'public' accounts, like engineer_01, engineer_02, etc.
But, this may not be necessary at all. What you really want IMO is to impersonate the user, instead of 'hacking' the account.
One way to do this, is to extend IdentityServer with a custom grant type using extension grants.
How this could work:
A signed-in user, who is allowed to impersonate users for the particular client/resource, requests an access token at the new impersonation endpoint.
The user sends the sub from the user to impersonate to the endpoint, where the user and (combination of ) sub are verified.
When access is granted a new (short-lived) access token is returned which can be used to impersonate the user, without having to know the credentials of the user.
The access token should contain information of the endpoint so it can be determined whether the user is impersonated.
We implemented an impersonation feature that is integrated into the browser-based sign in flow. If a user with permission chooses to sign in as another user then we add additional claims to their IDS4 authentication cookie which then supports issuing extra claims in the resulting token that reflect that it's an impersonation session and who the original actor is.
Navigate to client application
Sign in using whatever credentials
Check if any impersonation permissions exist (how these are defined is entirely up to you)
Prompt for impersonation account selection (or just continue as self)
Sign in as the selected account (with record of original actor)
Redirect to authorize endpoint
Issue tokens and redirect back to client application
A requirement is set upon me to implement impersonation for developers, of course only for development environment. I was wondering if it is possible to request a token for any AAD user without knowing the password. The flow I would want is:
Developer goes to web application to select a user he wants to impersonate.
The web application checks if the developer is in the AAD.
The web application checks if the developer has the necessary rights to impersonate.
The web application returns a token valid for the user the developer selected.
The developer can use this token to authenticate against the API, and for all intents and purposes is the impersonated user.
Any good alternatives to this approach are also welcome.
No, you cannot impersonate a user like this.
You can acquire an access token if you know their password and they don't have MFA etc. with the Resource Owner Password Credentials grant flow.
But if you want to do it in a better way, you could have the users who you wish to impersonate login to your app.
Acquire an access token + refresh token for them.
Then store the refresh token securely.
Now you can use the refresh token at any time along with your app's client credentials to acquire a token for that user.
Refresh tokens can and do expire though, for example if the user's password is changed.
But this could allow you to implement what you want.
I am wondering if it is possible to use Microsoft's Graph API in order to create a cookie in IE given the username and password, (preferably using C# or VB.net), so that when the user connects to sharepoint with IE, he/she won't have to log into sharepoint via the login screens.
I'm having difficulty searching for examples because most examples describe how to authenticate a user. I am not looking to authenticate a user though, I am looking to create and store a cookie to force a user login.
Thank you for any advice.
No, and this should never be done. First because cookies are simply not secure. Secondly because you should never be storing any encrypted password anywhere.
I'm really not sure how Graph API fits into the scenario you provided. Microsoft Graph is a REST based API. It doesn't authenticated users on its own, you pass in a valid access token with each call. How you retrieve that token depends on if you're using delegated or application permission scopes.
From the scenario you described, it sounds like you're looking for SharePoint Single Sign-On (SSO). There are a few ways to do this but generally it is done using ADFS and AADSync. There is a walkthrough for setting this up: Step-By-Step: Setting up AD FS and Enabling Single Sign-On to Office 365. Be forewarned however, this is not a trivial process.
I have a REST API written in C# and I need to authenticate with an existing Azure AD service. I currently have the username and password of the user wishing to authenticate. I need to authenticate with Azure AD and receive an access token from the server.
Can someone please point me in the direction of some articles/tutorials that explain how to do this?
You should avoid handling the users credentials. There are serious security implications when collecting a users credentials that are mitigated by using OAuth 2.0 or OpenID Connect to get a token without directly handling the credentials. Also, if you have your own credential collection UI then you may find that sign in fails in the future if multi-factor authentication is turned on. In that case, more information may be necessary to authenticate the user than you are collecting, a one time password for instance. If you allow Azure AD to present the authentication experience via OAuth 2.0 or OpenID Connect, then you are insulated from the specific authentication method being employed. Collecting the users Azure AD credentials is a bad practice to be avoided if at all possible.
I don't have enough detail on the exact scenario to be confident that the following sample applies, but it will at least provide a good starting point. This sample shows how to create a native app that calls a REST API that can then call an Azure resource in the safest way possible.
https://github.com/AzureADSamples/WebAPI-OnBehalfOf-DotNet
You can find lots of other samples here that can be used to construct a solution for your particular scenario.
https://github.com/AzureADSamples
If you provide some more detail I can give more specific guidance.
See: http://www.cloudidentity.com/blog/2014/07/08/using-adal-net-to-authenticate-users-via-usernamepassword/
Summary:
Create a UserCredential
UserCredential uc = new UserCredential(user, password);
Call one of the AcquireToken() functions with the UserCredential
public AuthenticationResult AcquireToken(string resource, string clientId, UserCredential userCredential);
public Task<AuthenticationResult> AcquireTokenAsync(string resource, string clientId, UserCredential userCredential);
I'd like to create a single sign on for multiple websites (sitea.com, siteb.com, sitec.com). All sites are with the same company. Any database is also with the same company/location. Some are asp.net web apps and some are forums. I'd like to try and abstract away the SSO so it is not tangled up with any one site. I've outlined my approach below:
user signs into sitea.com, which authenticates user. A sessionid is created by sitea.com.
a cookie is placed on the user's machine with username and sessionid. The sessionid is inserted into the database centralAuthDB, which all sites have access to.
user clicks a link in sitea.com that does SSO to siteb.com (forum).
siteb.com retrieves username and sessionid from the cookie. siteb.com then checks these credentials against centralAuthDB.
A match is made with centralAuthDB and the SSO is authenticated. However, the forum (siteb.com) also has its own database of users. The username is checked in this database as well and now the user is seamlessly logged into the forum.
Is the above secure and practical?
Should credentials be send to centralAuthDB via webservice?
Will the cookie need some generic name? Then the values for username and sessionid are placed in this cookie?
With any SSO, you're going to need a service that takes a credential and generates a secure authentication token. The token must be encrypted so that it cannot be forged; only the authenticating service would be able to decrypt it to check for validity. Then, that token can be passed around to whatever you wish--in a query string, most likely. Cookies are ruled out because they are inaccessible across host names.
As mentioned in the comments on your question, it's wise to investigate pre-existing solutions to this problem. Way smarter guys than you or I have spent thousands of man-hours hashing out all the problems with such systems.
My own personal choice would be OAuth as it's the implementation I'm most familiar with. You might also want to check out how Facebook does authentication for ideas on what, exactly, the token could contain.