I'm trying to build this scenario in windows client:
Picture of my desired scenario
Steps I did:
Client starts; it opens a window with a choice of the identity providers
End-user choose one of the identity providers (let's say Google)
It goes to next tab, where web-browser navigates to Google sign-in screen.
User signs-in, and authentication token (user id, etc.) are received.
Now I can login using Mobile Services, and access Azure tables, all is fine.
But now we want to use WCF service. How to obtain the IdP token in this scenario, to be used to obtain ACS SWT Token. I have access token, authentication token, user id, and much more information from IdP, but how can I either catch or forge IdP token from these informations?
I want to be able to access Azure table in a WCF service, while having the identity of a signed user from the client-side?
OK, after intensive search, I've found these links useful:
Azure ACS on Windows Phone 7
How To: Obtain SWT Security Token
How To: Display List Of Identity Providers
How to: Authenticate to a REST WCF Service
Related
I've tried acquiring token using ROPC with the username and password provided by client. But the error message was "parsing_wstrust_response_failed". Same as the error message (last error) described here
From this error message I understood my user is a federated user and cannot use this method. Is there any other way to acquire token for a federated user using username and password?
try
{
result = await app.AcquireTokenByUsernamePassword(scopes,
"joe#contoso.com",
securePassword)
.ExecuteAsync();
}
catch (MsalClientException ex) when (ex.ErrorCode=="parsing_wstrust_response_failed"){
}
No. There is no way.
You need to handle the authentication with another flow.
I mentioned this downside in my recent article: https://joonasw.net/view/ropc-grant-flow-in-azure-ad
First, a warning: You really should not use username/password in your app. In general, it's less secure and increases the risk you're exposing the associated environment to. It is also a brittle approach, as you will likely find Azure AD will require an interactive sign-in at some time in the future--probably at a very inconvenient time for you.
Second, a clarification: AcquireTokenByUsernamePassword will not always use the Resource Owner Password Credentials (ROPC) OAuth 2.0 flow. When MSAL discovers that the user is part of a federated domain name, the library will attempt a non-interactive username/password authentication if the federated identity provider publishes an metadata exchange document which includes an endpoint supporting this method. If this request succeeds, MSAL will then attempt to exchange the response (issued by the federated identity provider) for the normal token set from Azure AD (issued by Azure AD).
So, to answer your question: It depends. It is possible to use AcquireTokenByUsernamePassword with a federated user. However, it requires that the federated identity service support this. AD FS, which is the most common IdP to be federated with Azure AD, supports this is the "usernamemixed" endpoint.
Depending on what you are trying to build you could use the AcquireTokenByIntegratedWindowsAuth() instead. Our scenario was we needed a headless console app to be able to send emails and notifications to a Teams channel. We are also Federated, so username\password auth wouldn't work. But since we are running on on Windows we can use integrated auth.
I followed this guide to get the Access Token: https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/Integrated-Windows-Authentication
Our scenario did require a one time user consent, so the user the console app runs as had the proper permissions. https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/authorize?client_id={clientId}&response_type=code&scope={scopes}
I am currently building an API which requires OAuth2, but cannot find a library to use that will handle the single sign on in a native mobile app via RESTful API only. Most I've found only have a web popup, which has been vetoed for this project. B2C, which is currently functioning, is not capable of using ROPG. Is there a way to easily set this up with another library using C#.NET and Azure?
UPDATE:
Attempting to use B2C per Fei Xue answer below, we got to the point of getting an access token from Microsoft Graph.
In the body of the POST, we did the following:
resource=https%3A%2F%2FGraph.windows.net&client_id=[B2C Settings -
Applications -
AppId]&grant_type=password&username=rob%40[tenant].onmicrosoft.com&password=[password]&client_secret=[B2C Settings - Applications - App Key - client_secret]
Our error with the namespace was due to the usernames we were trying. This is a B2C tenant using email as the username and that was the reason for the namespace error. The only way we got past that error was to create a B2C user with the email address ending in the tenant, like so:
rob#[tenant].onmicrosoft.com
We are getting an access token now, but that token does not authenticate with our azure app service api app, which was the original goal.
What we are trying to accomplish is to send the username and password that is valid for a B2C signin and get an IdToken or Access Token that is valid for the api app. The api app connects to B2C via App Service Authentication settings configured for AAD with the Client ID and secret setup from the B2C Settings Application.
UPDATE:
Attempting to pass through the graph.windows.net token for authentication in our Azure web api, we added in the https://Graph.windows.net allowed token audience in our App Service – Authentication – Active Directory Authentication configuration.
However, passing the graph access token in the Bearer header to the API still results in
“Authorization has been denied for this request”.
Found out that if we make the Issuer Url blank like in the example below, it now accepts the Graph token!
However, this causes issues when trying to hit
https://[our_web_app].azurewebsites.net/.auth/login/aad
It goes to the common Microsoft login now. Previously it directed to our B2C sign up in policy because the Issuer Url was set to:
https://login.microsoftonline.com/[tenantname].onmicrosoft.com/v2.0/.well-known/openid-configuration?p=[B2C_SignUpIn_Policy]
In fact, if we also pull up the policy from within our app (which was working before removing the Issuer Url) to the sign in policy, we can sign in, but that returned Access Token now always comes back as Unauthorized in the web API calls.
Should the Issuer Url be left blank?
Also, since making the Issuer Url blank, the server takes much longer to respond to API calls when we send a request using a Graph access token in the Header Authorization Bearer. It went from taking about 1-2 seconds (using a valid B2C access token obtained from MSAL or the web login above) to taking about 10-15 seconds to respond that it is an authenticated request. That kind of speed is a show stopper for us. Does validating a graph call in this manner normally take this long?
The feature is now available in preview and works pretty well:
https://learn.microsoft.com/en-us/azure/active-directory-b2c/configure-ropc
Important note: The POST url mentioned in the documentation is wrong.
https://login.microsoftonline.com/{{Aad_Tenant}}/b2c_1_ropc_auth/oauth2/v2.0/
Must be:
https://login.microsoftonline.com/{{Aad_Tenant}}/oauth2/v2.0/token?p=b2c_1_ropc_auth
The calling application must have native client enabled, otherwise you will get this error:
AADB2C90224: Resource owner flow has not been enabled for the application.
The Azure AD B2C has already support the Resource Owner Password Grant flow, you can send the HTTP request like below to using this flow:
POST: https://login.microsoftonline.com/{tenant}/oauth2/token
resource=https%3A%2F%2FGraph.windows.net&client_id={client_id}&grant_type=password&username={userName}&password={password}&client_secret={secret}
Note: this flow only work for the local accounts as social identity providers(Facebook, Google, etc) don't support this.
Update
The token above is acquiring the token for https://graph.windows.net. To pass through the authentication of web API which protect by Azure AD, we need to specify this as the ALLOWED TOKEN AUDIENCES like figure below:
Update to the answer from #AlexAIT.
The URL in the documentation now works for AD B2C.
https://<tenant-name>.b2clogin.com/<tenant-name>.onmicrosoft.com/B2C_1A_ROPC_Auth/oauth2/v2.0/token
https://learn.microsoft.com/en-us/azure/active-directory-b2c/add-ropc-policy?tabs=app-reg-ga&pivots=b2c-user-flow#test-the-ropc-flow
If you get the error:
AADB2C90224: Resource owner flow has not been enabled for the
application
Navigate to application -> Authentication and select Enable the following mobile and desktop flows:.
Wait a few minutes and then it will start to work.
Github thread:
https://github.com/MicrosoftDocs/azure-docs/issues/50330
I work with Rob, and we did finally get the call to work with
https://login.microsoftonline.com/[tenant_ending_in_onmicrosoft.com]/oauth2/token
In the body of the POST, we did the following:
resource=https%3A%2F%2FGraph.windows.net&client_id=[B2C Settings - Applications - AppId]&grant_type=password&username=rob%40[tenant].onmicrosoft.com&password=[password]&client_secret=[B2C Settings - Applications - App Key - client_secret]
Our error with the namespace was due to the usernames we were trying. This is a B2C tenant using email as the username and that was the reason for the namespace error. The only way we got past that error was to create a B2C user with the email address ending in the tenant, like so:
rob#[tenant].onmicrosoft.com.
We are getting an access token now, but that token does not authenticate with our azure app service api app, which was the original goal. What we are trying to accomplish is to send the username and password that is valid for a B2C signin and get an IdToken or Access Token that is valid for the api app. The api app connects to B2C via App Service Authentication settings configured for AAD with the Client ID and secret setup from the B2C Settings Application.
UPDATE:
If I add ?p=[B2C SignUpIn Policy] to the POST, then we get the following error:
AADB2C90224: Resource owner flow has not been enabled for the
application.
We are looking into a way to request a JWT token from ADFS 2016 via webservice call by sending a user UID, which is stored in a database or in AD LDS. The token should contain the full domain username as a claim. A C# service would request the token without user GUI interaction (UID provided by an ID card), and then forward it to an intranet web application.
Is this possible with OAuth 2.0 or WS-Trust 1.3 in ADFS 2016, and what steps would be involved?
Right now I have tried using OAuth 2.0 (HTTP POST to /adfs/oauth2/token), but haven't been able to correctly configure ADFS (application groups, relaying parties, ...) and sending the correct HTTP parameters to even get a token by providing username/password.
It would be great if somebody could point me in the right direction.
EDIT
A more detailed description of what we want to achieve:
Goal is to create a windows service which handles NFC card login and sends JWT with user information to arbitrary web applications.
C# windows service reads card UID from a NFC card reader.
Windows service requests JWT from ADFS by providing card UID. That can be OAuth or WS-Trust, whichever works.
ADFS looks up card UID from a confidential database. The database entry also contains the username. It could then further enrich this data by finding the domain user in ADLDS.
ADFS creates token containing at least the domain user name and sends it back to the C# windows service. No user interaction with ADFS login screens required.
Windows service receives token and forwards it to preconfigured web application login handler.
Web application validates token signature and handles login.
The credential in this case would solely be the card UID. Is this possible with ADFS? If not, my backup plan would be to create the token directly in my windows service.
I have a MVC5 website and WebApi using ASP.Net identity. I have configured the website to use Microsoft Account as an external login.
The Windows Store App will use the WebApi, and the user should have the same identity when using their Microsoft Account from either the website or the app. As users are already logged into their Microsoft Account when using Windows Store App, I don't want them to have to enter their credentials again.
I'm wondering what is a good way for my app to be able to access the WebApi. Can I retrieve the Microsoft Account authentication token and pass that to my website's token endpoint with an authorization code grant in order to retrieve the token for my app to use to access the WebApi? Is there another way?
I want to avoid making changes to my WebApi's Account Controller as this process does not really fit into the MVC part of the website as it does not need to redirect to views, etc. So I plan to extend the Token endpoint with a custom grant type (e.g. exchange), which will return the local token to the consumer. Consumers will send the Token endpoint a request with a grant_type of exchange, my app's client id and secret, the name of the external provider (e.g. MicrosoftAccount), and the access code from the external provider. For example, the app will send a request like this:
http://myhost.com/token?grant_type=exchange&client_id=CLIENTID&client_secret=SECRET&provider=MicrosoftAccount&code=LIVESDKACCESSCODE
I'll provide an implementation of the ApplicationOAuthProvider's GrantCustomExtension method, the pseudo code will be like this
validate the client id and secret
If client id and secret are valid, use the access code to get an access token from the Live SDK
parse the Live SDK access token to retrieve the id value
try to find the corresponding id value in the AspNetUserLogins table
If the login is not found, add a new AspNetUser record for the user and a record in the AspNetUserLogins table
create a token for the user and return the token
Once the app has the token, it can be stored in the Credential Locker for any other calls to the WebApi
I have a Native Client registered in our Azure AD.
When i'm using
var ar = _context.AcquireToken(resource, clientId, returnUri);
It opens the Prompt for Username and Password. If I enter them correctly I get a valid AccessToken and everything is fine.
When I'm now trying to enter the credentials in code, via UserCrendtial:
var credential = new UserCredential("username", "password");
var ar = _context.AcquireToken(resource, clientId, credential);
But both resulting in an Error when I'm trying it with the directly entered Credentials.
AADSTS65001: No permission to access user information is configured
for '4915f024-blah-blah-blah-f580ab5b0487' application, or it is
expired or revoked.
I have tried the normal (string, string) and the (string, SecureString) overload of the UserCredential.
I have tried it with the exact same combination of username & password, which I have entered in the Prompt, of the first overload from AcquireToken.
I have also tried to give the Application in Azure all the Delegated Permissions:
Read directory data
Read and write directory data
Access your organization's directory
And added Windows Azure Service Management API Application with Permission:
Access Azure Service Management
Nothing helped.
As a sidenote, the Application in the Azure has permissions to a SharePoint O365 Tenant. To Read and Write ListItems I don't know if this is relevant. The Resource i'm passing through is the SharePoint Adress.
I don't need any user access over the Graph Api to the Azure. I only need that AccessToken to access our SharePoint Online.
Edit:
Architecture:
Description:
We have a Web Api Project which handles the User Authorization, Load Balancing etc. This Web Api Project, will be queried by either Native Dekstop Clients or Hybrid HTML5 & Javascript Mobile Device Apps.
The Web Api Project needs to Read, Create, Update & Delete Data from our SharePoint O365 Tenant. So this where I need the AccessToken to init a ClientContext or send i via a rest response.
Since the Web Api handles the User authorization, there is an endpoint for users to login already and in this endpoint I want to acquire the Token. That's why I want it to be silent, because the "flexbile browser popup" is already there.
Maybe I don't need in this scenario the Token acquiring with Username / Password, but then I don't know how to configure the Azure App right to work with all the different native client's.
not sure if it's your case but you can use :
built in auth (setting 'on' in webapp options; then create express app or/and then chose advanced mode with same apps ids);
then add AD native client app;
login to old classic portal there select native app and in config add access to you express/advacsed web app;
after that you will able login in browser; and with adal lib will able login to access you api from mobile devices;
for more see ms docs and samples;
The direct use of username and password has important limitations, please make sure you are not stumbling on any of the ones listed in http://www.cloudidentity.com/blog/2014/07/08/using-adal-net-to-authenticate-users-via-usernamepassword/.
Also note, nothing that requires displaying a user consent screen (as all the permissions you described will) or specific disambiguation steps (like trying to use a guest user from X to access a resource protected by tenant Y) will work.
What is your scenario? Any specific reason for which you want to use username/password instead of the more flexible browser popup?