Azure AD | Conflict when logged in with another Azure Account - azure-active-directory

I have a Asp.net MVC application that uses Azure AD and OpenID Connect OWIN middlewares to handle authentication. Everything works fine except for one thing : if a user is already logged-in on another Microsoft Application lets say a Office 365 account or maybe a live mail account, when trying to login it recives a page saying that it is not allowed to log into my app, which is correct, but some how I need to catch that situation in my code to allow the user to sign in with a different account. Is there a way of doing that? This is by design? I mean : the user have to log in only with a live/azure account at the time ? I couldn't find any documentation about this.

As of today there is typically one user at a time, but we will soon support for you a way to select a specific user instead of automatically signing you in with the most recent one.
One way you can work around this today is by injecting the parameter "prompt=login" in your sign in requests. You can do that in the RedirectToIdentityProvider notifications, similarly to what is showin in http://www.cloudidentity.com/blog/2014/11/17/skipping-the-home-realm-discovery-page-in-azure-ad/ for domain_hint. This will cause the sign in experience to always start with a fresh prompt even if the user is already signed in. The draw back is that you'll never get SSO this way. Hopefully our account switiching feature will become available soon, keep an eye on http://blogs.technet.com/b/ad/ for announcements

Related

Salesforce Server-to-Server integration without any user involved

I am working on a integration with Salesforce using REST APIs and, as part of the project, I need to send updates to Salesforce and these updates are not user triggered, they are system triggered.
Because of that, what I expect to see on Salesforce Field History is not a user name but the name of our Connected App (the app that made the update).
What I see today is the user name because the way the integration was made initially using OAuth Authorization Code flow.
To change that part of the project, I followed the link (OAuth 2.0 JWT Bearer Flow for Server-to-Server Integration): https://help.salesforce.com/articleView?id=sf.remoteaccess_oauth_flows.htm&type=5
Making that, I was expeting to generate a token for a System, not for a User, but that's not what happened: when I used the token generate from the JWT Bearer Flow and ran the update, the Field History still shows the user name.
What could I do then?
Which are the options in Salesforce to achieve the behavior I'm expecting?
The most important, in my opinion, is to have a Token for our system, not for a user.
Thanks!
Everybody is an user in Salesforce. Even if you access unauthenticated pages (some contact us form? case or lead capture) - it gets tracked under special Guest User.
It sounds stupid but gives you unified interface to control permissions (Profiles/Permission sets). You want guests to access only FAQ articles and make cases? Sure thing, do it in profile, don't get paranoid about people trying to guess right URLs. You think an app was hacked? You can terminate the session just like any other "user". Want to allow login only in certain hours and from certain IP? Sure.
An app connecting with JWT will still need username (main difference being it's "just" certificate for signing the request instead of password).
Your best bet is to create dedicated "Mr System", "SystemX integration" account. It sounds like waste of license but in the long run saves you questions "why did you edit my account at 1 am" and you could even use it as backup account if you use SSO and it ever fails...

Salesforce: How to automate report extraction as JSON/CSV

I am new to Salesforce, but am an experienced developer. I am provided a link to a Salesforce report, which mostly has the right filters (query). I would like to use an REST API to pull that information as CSV or JSON so that I can do further processing on it.
Here are my questions:
Do I need special permissions to make API calls? What are they?
Do I need to create an "app" with client-key & secret? Does my admin need to grant me permission for this too?
There are a lot of REST APIs from Salesforce, which one do I need to get the info from the report? Analytics?
How do I authenticate in code?
You'd have to work with the System Administrator on the security pieces. Anybody who knows how the company works, can all users see everything, is there Single Sign-On in place, how likely is the report to change...
You will need an user account to pull the data. You need to decide if it'll be some "system account" (you know username and password and have them stored in your app) or can it run for any user in this org. It might not matter much but reports are "fun". If there will be data visibility issues 6 months from now, you'll be asked to make sure the report shows only French data to French users etc... you can make it in report filters or have multiple reports - or you can just use current users access and then it's the sysadmin that has to set the sharing rules right. (would you ever think about packaging what you did and reusing in another SF instance? Making a mobile app out of it? Things like that, they may sound stupid now but will help you decide on best path)
The user (whether it'll be system account or human) needs Profile permissions like "API Enabled" + whatever else you'd need normally ("Run Reports" etc). If you're leaning towards doing it with system user - you might want to look at Password Policies and maybe set password to Never Expires. Now this is bit dangerous so there would be other things you might want to read up about: "API only user" (can't login to website), maybe even locking down the account so it can login only from certain IP ranges or at certain times when the job's supposed to be scheduled...
Connected App and OAUth2 stuff - it's a good idea to create one, yes. Technically you don't have to, you could use SOAP API to call login, get session id... But it's bit weak, OAuth2 would give you more control over security. If you have sandboxes - there's little-known trick. You can make connected app in production (or even totally unrelated Developer Edition) and use client id & secret from it to login to sandboxes. If you create app in sandbox and you refresh it - keys stop working.
(back to security piece - in connected app you can let any user allow/deny access or sysadmin would allow only say these 3 users to connect, "pre-authorize". Could be handy)
Login - there are few REST API ways to login. Depends on your decision. if you have 1 dedicated user you'll probably go with "web server flow". I've added example https://stackoverflow.com/a/56034159/313628 if you don't have a ready SF connection library in your programming language.
If you'll let users login with their own credentials there will be typical OAuth "dance" of going to the target page (Google login, LinkedIn, Twitter...) and back to your app on success. This even works if client has Single Sign-On enabled. Or you could let people type in their username and pass into your app but that's not a great solution.
Pull the actual report already
Once you have session id. Official way would be to use Reporting API, for example https://developer.salesforce.com/docs/atlas.en-us.api_analytics.meta/api_analytics/sforce_analytics_rest_api_get_reportdata.htm
A quick & dirty and officially not supported thing is to mimic what happens when user clicks the report export in UI. Craft a GET request with right cookie and you're golden. See https://stackoverflow.com/a/57745683/313628. No idea if this will work if you went with dedicated account and "API access only" permission.

Delegate and impersonate as a user with admin/app credentials

One thing I do currently in an enterprise app is logon to a single admin email account that has delegation over other users and using delegation, we are able to manipulate email/calendar/contacts of users.
I'm looking to use the Microsoft Graph API and I have managed to use admin delegation and gain access to various resources, however last modified (on Onedrive/Sharepoint) is showing the app instead of an individual user.
I understand I can use Oauth and logon as individual users, capture a token and then do what I need under the context of that user, but, I need to do this server side where tasks run. Is there anyway to use admin approved delegation/impersonation from the app so that the users don't have to signin?
e.g. standard that works:
https://graph.microsoft.com/v1.0/sites/my-site.office.com/drive/root:/file.txt:/content
Looking to add a user tag, but this doesn't work:
https://graph.microsoft.com/v1.0/user/{id-of-user}/sites/my-site.office.com/drive/root:/file.txt:/content`
After searching for ages, the closest I have read seems to be in here however, I was wondering if there was a standard way of doing this - I haven't been able to get the JWT part of this working (and not sure if this is even the correct thing I am looking for).

How to support multiple login scenarios in multi-tenanted Azure Active Directory (AAD)

Our application (referred to as "XYZ_App" below) is a multi-tenant SaaS application. We are in the process of making it available for Microsoft AppSource as a multi-tenanted "Web app / API" (referred to as "AppSourceXYZ_App" below).
We started our OpenID Connect implementation with endpoints pointing to “common” as per stated in the documentation when multi-tenancy is desired/required.
In XYZ_App, we added information in the system to know what AAD instance each XYZ_App tenant is associated with (using the GUID Microsoft assigned to this AAD instance, we are NOT using the "rename-safe.onmicrosoft.com" representation).
When using the “common” endpoints, we had to manually validate the issuer from the JWT to make sure it was the expected one: a user could access XYZ_App requesting access to XYZ_App’s tenant associated with contoso.onmicrosoft.com, get directed to “login.microsoftonline.com/common” to authenticate and then decide to authenticate with a user from another AAD instance (referred to as "anotherAADInstance.onmicrosoft.com" below). In this scenario, even though a user could successfully authenticate on anotherAADInstance.onmicrosoft.com, XYZ_App’s redirect URI must make sure the JWT issuer is the one from contoso.onmicrosoft.com. I’ll refer to this setup as Scenario_1.
With that scenario in mind, we thought about NOT using “common” and customize the requests going to login.microsoftonline.com on the fly; attempting to “jail” requests to be forced to authenticate against a specific AAD instance. We would still need to perform our validation in the redirect URI to make sure the issuer is the appropriate one, but we thought this approach might make our lives easier. I’ll refer to this setup as Scenario_2.
Do you envision Scenario_2 is viable in the long run or is it too short-sighted ? Based on my current knowledge of OpenID Connect, one limitation I can see with Scenario_2 is that it would become problematic to support “broker accounts” into our app.
Explanation of “broker accounts”: in our industry, some external users are allowed access to the system. Let’s say I have a company called “BrokerCo” (with their own brokerco.onmicrosoft.com AAD instance) who has 2 employees: Broker1 and Broker2. BOTH anotherAADInstance and contoso hired Broker1 and Broker2 to get broker services to perform tasks in XYZ_App; requiring XYZApp to grant them access. What is the ideal way for authentication from an OpenID Connect standpoint ? If XYZ_App were to use “login.microsoftonline.com/common” for authentication (like in Scenario_1; as opposed to “jailed” access like in Scenario_2), Broker1 and Broker2 could authenticate with brokerco.onmicrosoft.com (no AAD "External users" for anotherAADInstance nor contoso), but they would then get to redirect URI with an issuer that is different than what XYZ_App’s anotherAADInstance and contoso tenants are configured for... I feel like I’m back to square 1...
Do you have suggestions or pointers to solve this issue ?
Background context:
While playing with OpenID Connect issuers, I got the following error message:
AADSTS50020: User account 'testuser#anotherAADInstance.onmicrosoft.com' from identity provider 'https://sts.windows.net/XXXXXXXX-fake-GUID-9bZZ-XXXXxxxxXXXX/' does not exist in tenant 'XYZ Publisher' and cannot access the application 'YYYYYYYY-fake0-GUID-YYYYyyyyYYYY' in that tenant. The account needs to be added as an external user in the tenant first. Sign out and sign in again with a different Azure Active Directory user account.
Thanks in advance !
Your question has multiple layers, trying to address most of them:
AppSource is about trial experiences for new users: this mean that any corporate account around the globe can potentially be an user of your SaaS application - or at least to the trial experience of your application, therefore the first thing you need to think when integrating with AppSource is how easy it has to be for a potential user to experience your app for the first time.
With that in mind, AppSource recommends that the trial of application is build on such a way that allows any user from any organization to sign-in, and therefore a multi-tenant approach for your application is the recommended setup for any application.
The single-tenant approach requires more control on your side, and for a trial experience - it means that the user cannot try your application right away because the operation you have to do on your single-tenant application is to add the user to an Azure Active Directory tenant as a guest user. This guest account will need then to wait receiving an email to accept the invitation to join to this tenant you are adding the user to then sign-in to your application.
Therefore your scenario 1 is the best scenario thinking on a trial experience in general, and also in general require less management (as you'd not need to create/ manage each individual account that needs to access your application as guest users of your Azure AD instance).
However some concerns you listed - that this scenario bringing are valid: Because you are accepting the common endpoint, you are saying basically that any user can sign-in to any tenant to your application, and this may not be desirable. In addition, the scenario you listed that a user can generate a token for any application is also valid, however, you can add additional checks to make this more secure and that any token generated by another authentication is blocked:
You can validate the 'audience' claim to guarantee that the token was issued to your application
You can eventually check the 'tid'/'iss' claims against of a list of tenant Ids in your database to see if that the user's organization is a valid organization in your application -- this would be valid for non-trial users/ organizations.
More information in this article.
About scenario '2' and broker accounts:
This scenario could be interpreted in two different ways:
Broker accounts are guest accounts of a customers' Azure AD tenant
Broker accounts are third party accounts but are not actually added as a user of anotherAADInstance or contoso AD
If your case is '1' then you're right: if your application needs to authenticate guest users that belong to another Azure AD tenant, then common endpoint could not be used directly.
If your case is '2' then what you'd need to do is to continue using the common endpoint and somewhat after the user is authenticated ask them to choose the company. I am describing this on generic terms without fully understanding this scenario. Perhaps this is not simple as you want the remote company to control this and not the user - so some additional complexities may need to be handled here.
A note is that if your scenario is scenario 1. - in theory - you can still use an hybrid approach, where you'd ask user to type the username inside the application and the company that they want to sign-in, then check if you need to validate the user against common or tenant-id endpoint, preparing the request and then sending a login_hint argument when authenticating. More information here

Empty GUID error when using Azure AD consent flow

I'm currently trying to integrate with Azure AD using the admin consent flow.
I've set up an app in our domain, set a few permissions on it and am then navigating to the following link:
https://login.microsoftonline.com/mytestdomain.onmicrosoft.com/oauth2/authorize?client_id=12345678-1234-1234-1234-123456789012&response_type=code&redirect_uri=http://example.com/responsehandler&resource=12345678-1234-1234-1234-123456789012&prompt=admin_consent&state=12345
(Some of the values here have been swapped out for "example" values)
When I navigate there I get asked to sign in, which I do using a different test domain into which I want to import the app.
After signing in I'm shown a list of all the permissions that the app needs (which appear to be correct), I click accept but then I get the following error:
AADSTS90002: Requested tenant identifier '00000000-0000-0000-0000-000000000000' is not valid. Tenant identifiers may not be an empty GUID.
I'm not sure where this empty GUID is coming from and after some searching I can't find any reference to what might be causing it.
Daniel Camargo's comment above seems to have done the trick.
When I navigated to the login.microsoftonline.com link I was logging in with the user that created the domain.
If I log in with a test admin user that I created it works as I'd want.
I am not convinced that we had exactly the same problem, given that my case was involving a Cordova application, but I will share my scenario anyway:
I created a trial account for my proof of concept and for that I used my personal Microsoft account that I will call mypersonalaccount#outlook.com.
Thus, mypersonalaccount#outlook.com is now part of 2 directories: the outlook.com and my recently created mypersonalaccount.onmicrosoft.com.
When I was trying to authenticate in my Oauth2 application using mypersonalaccount#outlook.com I got that error. My humble guess is that the error is related to some sort of collision between the 2 accounts.
I later created a user1#mypersonalaccount.onmicrosoft.com and a guest account using my gmail account. Everything worked fine with these ones.
Was having the same problem, and the same after 1 week of work by the azure team, was solved.
My problem was being trying to log in to VSTS with AAD accounts.

Resources