Authentication flow Service to Service Microsoft Graph and Bookings API - azure-active-directory

I am building a custom mobile application that has a client, custom backend server (I'm building) and interacts with numerous other api's. One of these api's is Microsoft bookings.
The problem I'm facing is I need to be authenticated via server to server, with a shared client secret. I'm aware of the numerous docs from MS but have yet to find a solution. I'm wondering if Server to server is even possible with Bookings.
I am able to get an access_token server to server with these permissions. (I have granted 'all permissions' to this app in Azure AD already).
"roles": [
"Calls.JoinGroupCall.All",
"OnlineMeetings.Read.All",
"OnlineMeetings.ReadWrite.All",
"Application.ReadWrite.OwnedBy",
"Calendars.Read",
"People.Read.All",
"Application.ReadWrite.All",
"Calls.InitiateGroupCall.All",
"Directory.ReadWrite.All",
"Calls.JoinGroupCallAsGuest.All",
"Sites.Read.All",
"Sites.ReadWrite.All",
"Sites.Manage.All",
"Files.ReadWrite.All",
"Directory.Read.All",
"User.Read.All",
"Calendars.ReadWrite",
"Mail.Send",
"ProgramControl.Read.All",
"ProgramControl.ReadWrite.All",
"Calls.Initiate.All"
],
Those are the permissions from the decoded token. When I go to make calls to the Bookings api I receive 401.
I can however use this token to access different graph endpoints no problem.
I will note, that I am able to make successful calls to the bookings api through Graph Explorer with my account, not related to this 'Application in Azure AD'.
Does this resource in Azure AD need a bookings License?
Is this even possible S2S?
Are there any other ways to bypass this without user credentials?
Thanks.

So I spent over a week trying to solve this problem due to the MS doc nightmare. I'm only posting to help others!
Bookings doesn't support service to service yet. So if you wan't to implement this without a user physically signing in, IE. If you have a dedicated booking admin account credentials you have to hard code the clients credentials.
I found my answer here https://stackoverflow.com/a/49814924/9105626

Microsoft Bookings API doesn't seem to support "Application Permissions" so far.
Only permissions available are "Delegated Permissions", which means your token has to be acquired with the context of a signed-in user.
Here are two Microsoft documentation sources that I came across:
Microsoft Graph Permissions Reference - Please look at the "Bookings Permissions" section.
Microsoft Bookings Samples
I know you mention Server to Server authentication using a client secret. AFAIK, that case will NOT work directly, because clientId and clientSecret only provide an application's identity (which can't be assigned any permissions because there are no relevant application permissions available for this API).
Just in case you can have some User context involved, here is code from bookings samples link above, to acquire the token in a Native application using ADAL
var authenticationContext = new AuthenticationContext("https://login.microsoftonline.com/common/");
var authenticationResult = await authenticationContext.AcquireTokenAsync(
"https://graph.microsoft.com/",
clientApplication_ClientId,
clientApplication_RedirectUri,
new PlatformParameters(PromptBehavior.RefreshSession));
// The results of this call are sent as the Authorization header of each HTTPS request to Graph.
var authorizationHeader = authenticationResult.CreateAuthorizationHeader();
Suggestions on ways to make this scenario work
On Behalf Of Flow
Your mobile application client could prompt a user for credentials to act on Behalf of the user and call your backend web API, which in turn calls the downstream API like Bookings API. This is called Service to Service Calls on behalf of the User
Here is a code sample which shows exactly this with a native application (WPF) and an SPA. In your case, just replace the WPF application with your mobile client application for understanding purposes and rest of the scenario becomes very similar.
Calling a downstream web API from a web API using Azure AD
ROPC Grant (Not Recommended)
Resource Owner Password Credentials grant can help as your application will have end user password available to it, but it has multiple issues and any security guidance will discourage you from using it.
ROPC opens up security risks, doesn't follow best practices and has functionality issues as well. ROPC doesn't work with MFA enabled users as well as federated authentication users.
For all practical purposes, you should avoid ROPC as long as possible. You can find the same recommendation in ADAL documentation itself and multiple other documentations from Microsoft or even generally about OAuth 2.0.

Related

How does client credential flow work in Workload identity federation?

For my current ASP.NET Core MVC application I authenticate directly with a web app registered in Azure AD Portal. This provides me with an access token so on the backend of my web application I can use MS Graph with my users specific account (ie add files to their onedrive , email, etc). However, my organization also has Okta which a lot of applications authenticate against. So I was trying to determine to authenticate through Okta (which has a much cleaner sign in process IMO) as well as authenticate against Azure AD and get an access token. Through my research I found something in my web application registration in Azure AD called Workload Identity Federation. This led me to this useful video
https://www.youtube.com/watch?v=wZ0gCJYMUKI
and also microsofts info site:
https://learn.microsoft.com/en-us/azure/active-directory/develop/workload-identity-federation
This seems to answer what I want which is to use Okta but allow me to still use MS Graph for my users since it will authenticate against Azure AD (correct me if I am wrong and this is for something else). My issue is none of these resources really go into depth regarding how the access token is passed to my application so I can use MS Graph. My research this is called client credential flow since my application only has delegated permissions so it requires the users to log in and it basically allows my web app to act on their behalf when using MS Graph. So I am trying to understand and fill this void of information regarding how client credential flow fits into Workload Identity Federation and is this the solution to my problem.

Office-Addin Single Sign On and API Scopes

The Office Addin for Excel provides the method:
OfficeRuntime.auth.getAccessToken(OfficeRuneTime.authOptions)
to call the Azure Active Directory, log in the user and gain access to the users profile. The method brings up a dialog box asking the users consent for the Office App to access their profile. The consent box also includes the grants to my Web App (Angular web site that runs in the Excel Taskpane) and includes the words "If you accept, will also have access to your user profile information"
All good. But my Web App communicates with my API, which requires an additional granting of consent for my API to access the users profile.
Is there any way to cause the dialog box invoked by 'getAcccessToken' to also grant permission to my API?
When I login using MSAL as a fallback method (not getAccessToken(), but using an excel dialog box with MSAL configured as per the various Microsoft Walkthoughts), the consent box DOES include both my WebApp and my WebAPI. And authentication works correctly.
I note that the Manifest file has a tag. I had hoped that adding the Scope to my API in here would cause the Office-Addin to request consent to it, but no banana, it does nothing.
Any Ideas?
I do note that getAccessToken() deliberately does not return an access token to MS Graph, with the Microsoft Documentation citing 'security concerns', and such access to Graph must be via Server Side Code using the On-Behalf-Of flow, perhaps similar reasoning does not permit me to gain consent to any API using getAccessToken(), but what then are these section in the manifest file for? I have really struggled to get SSO working with Office Addins, there are so many nuances and unexpected behaviours.
The getAccessToken method calls the Azure Active Directory V 2.0 endpoint to get an access token to your add-in's web application. That enables add-ins to identify users. Server-side code can use this token to access Microsoft Graph for the add-in's web application by using the "on behalf of" OAuth flow. This API requires a single sign-on configuration that bridges the add-in to an Azure application. Office users sign-in with Organizational Accounts and Microsoft Accounts. Microsoft Azure returns tokens intended for both user account types to access resources in the Microsoft Graph. Read more about that in the Microsoft identity platform and OAuth 2.0 On-Behalf-Of flow article.
In answer to my own question,
It is NOT possible to cause the dialog box invoked by 'getAcccessToken' to also grant permission to my API
I have written a lengthy response to this in my answer to this question
Office-Addin MSAL Single Sign In SSO: How to Refresh the Access Token?

Programmatic (API calls) User Authentication using Azure AD B2C instead of login.microsoftoneline.com form

New to Azure AD... So please don't be too harsh if this is off target. :-)
Technology Stack - Latest Angular 2 with C# Middle tier and latest .Net Framework.
Ideally, What we want to do is use Azure AD B2C to store user credentials and to do the authentication - but we want our 'own' forms on our site to do the login Forms capture and logging - then pass the credentials through an API (REST?) Call (using MS Graph SDK?) to Azure AD B2C and then check the call return for the Authorization content message.
Couple of reasons - control of the application flow, Logging and the "flickering of the URL" (i.e. going from our site URL to login.microsoft... URL and then back to our sites URL).
Is this doable without doing a hack?
Thank you in advance for your help and patience!
You are looking for the "Resource Owner Password Credentials".
This is not currently supported for Azure AD B2C, but you can give user feedback to the B2C team that you want this through the Azure Feedback Forum: Add support for Resource Owner Password Credentials flow in Azure AD B2C and headless authentication in Microsoft Authentication Library
You should also see updates at that location if and when they implement this feature.
The resource owner password credentials flow is now in preview.
In Azure Active Directory (Azure AD) B2C, the following options are
supported:
Native Client: User interaction during authentication happens when
code runs on a user-side device. The device can be a mobile
application that's running in a native operating system, such as
Android, or running in a browser, such as JavaScript.
Public client flow: Only user credentials, gathered by an application, are sent in
the API call. The credentials of the application are not sent.
Add new claims: The ID token contents can be changed to add new claims.
The following flows are not supported:
Server-to-server: The identity protection system needs a reliable IP
address gathered from the caller (the native client) as part of the
interaction. In a server-side API call, only the server’s IP address
is used. If a dynamic threshold of failed authentications is exceeded,
the identity protection system may identify a repeated IP address as
an attacker.
Confidential client flow: The application client ID is
validated, but the application secret is not validated.
From here.
Note that one disadvantage of doing what you're requesting is precisely that you can do "login forms capture and logging", so your application has a chance to see the credentials and perhaps take copies of them; thus your users have to trust you to behave.
The normal web-based flow means that your application doesn't need to be trusted; it never even sees the password at all.

Gmail API Access Single User Without Domain Wide Delegation

We have a bit of a dilemma that we are running into with a couple applications that are trying to read a given users email without user interaction to authorize. The key to this approach is that we want no user interaction, and want to load the client server application with the proper JSON credentials downloaded from the Google Developer Console.
I have this approach working for programs where we create a service account in the Developer Console, and then delegate domain wide authority to that account with the proper scope access. However what we are hoping is that we don't have to delegate domain wide authority, and just read the users email who created this developer console project. I have tried many different types of solutions for this, but always run into the same limitation that I have to grant domain wide access.
What I am wondering is if there is any way to gain access to a single users mailbox using a server to server type approach and not have to grant domain wide access?
I appreciate your help with this issue!
There is no supported authorization flow for what you want to do. You must either use a service account that has been delegated domain-wide authority, or you must use a 3LO flow that involves user consent.
It seems you're looking for OAuth for Server to Server Application. You will also be using a service account. But, granting of domain-wide authority for service accounts is an optional thing. You don't have to enable it if you don't want to.
To support server-to-server interactions, first create a service
account for your project in the Developers Console. If you want to
access user data for users in your Google Apps domain, then delegate
domain-wide access to the service account.
Then, your application prepares to make authorized API calls by using
the service account's credentials to request an access token from the
OAuth 2.0 auth server.
Finally, your application can use the access token to call Google
APIs.

API authentication with ADFS and Angular.js

I'm tried to build a new rich application and i'm having some problems designing the authentication process.
I've only two requirements :
An API needs to be available
An ADFS needs to be used to authentication
My first thoughts was to build the API and to use Angular.js for the frontend. However, I can't see how the authentication should work.
My API needs to be available though scripts. As far as I saw, the ADFS authentication always display t the webpage for the authentication process.
API are usually secured with OAuth2. We used an client id and a client secret to generate a token. But I can't have this behavior with an ADFS.
The only solution I see is to provide two authentications behavior with my application. One with the ADFS for the web access and in the web interface, add a possibility to generate a client id and a client secret associated with an user account that could be used for the API to the headless authentication.
Someone has already faced this kind of scenario?
Thanks a lot!
I assume the 'ADFS needs to be used for authentication' really means 'users should be able to use their Active Directory domain credentials to authenticate'.
If that is the case, you should take a look at Thinktecture IdentityServer. It's an OAuth2 authorization server that you can use with a Active Directory identity provider.
P.S. ADFS 3.0 that comes with Windows 2012R2 only supports the authorization code grant, which is not suitable for JavaScript apps.

Resources