Using the OAuth Client Credential grant flow to authenticate with Microsoft Identity Platform
Requirements: IPWorks, Cloud Keys, Cloud Mail, or Cloud Storage
The Active Directory Identity Service supports the Client Credential grant flow for Microsoft Graph API and Office365 Exchange services.
- App Registration Page
- Component Setup
The Active Directory Identity Service offers the Client Credential grant type for applications that run in situations where user interaction is difficult. Microsoft recommends that this grant type only be used in applications that are difficult to access, including web apps, web API apps, and daemon/service apps. This is because the client credential grant flow requires the use of application scopes, which require a client secret or client certificate to be configured in order to enable.
The client credential flow, like most OAuth flows, has two phases. The first phase requires the application to obtain consent for the scopes so that it can access protected resources (e.g. access the mailbox to send an email). The difference is that in the client credential grant flow, this is done via the Administrator of the tenant rather than the user of the protected resource. This first step only occurs when setting up the application in the working environment. More information related to how the administrator provides consent for the scopes is included later. The second step involves authenticating with the token server; this does not require any user interaction, which is one of the primary benefits of the client credentials grant flow. The user is required to provide extra credentials (i.e. a client secret or certificate) alongside a client ID. More information on acquiring the credentials and making this request is included later.
App Registration Page
The first step in configuring your application to use the client credential grant flow is to register it with Azure. More information on application setup and registration can be found here.
Multitenant vs. Single Tenant
In the client credential grant flow, Microsoft requires that the application be either single tenant or multitenant. Due to the lack of user consent, personal accounts can not be used. You must consider who will have access to the application when deciding which account types to allow. When the admin consents to the scopes, they consent for the entire tenant. If multiple tenants are consented, then the same credentials can be used by the application to access all of their combined protected resources. More information on the account types can be found here.
Platforms and Redirect URIs
The client credential grant type does not require any special platform configurations; thus, one does not need to be added. If you are looking to generate an admin consent URL using our OAuth component (more information later on), then you will need to add a redirect URL to the Web platform type. Typically, this URI will look something like "http://localhost:PORT". At this time, Microsoft does not perform port matching, so the port specified does not need to match the port in the request's redirect_uri parameter. More information on the platforms and redirects can be found here.
When adding scopes for your application, you will need to add "Application permissions" scopes rather than "Delegated permissions" scopes. Microsoft recommends only requesting what is needed for the permissions in the case that the application or the credentials become compromised. More information on the permissions can be found here.
Microsoft requires that credentials are provided for any application that is using the client credential grant flow. The two types of credentials that are supported by our OAuth component are client secrets and certificates. Microsoft recommends the use of certificates for a higher level of security, but they are typically more complicated to set up and maintain than client secrets. More information on the credential types can be found here.
All permissions will require that an Azure administrator grant consent for the scopes presented by the application. There are two ways for an admin to provide consent. If the admin is in the same tenant as the application registration, they can consent directly from the Azure Portal. Otherwise, an admin consent URL will need to be generated which can be done using the OAuth component.
When the administrator is in the same tenant as the application registration, they can use the app registration node to consent to the "application permissions" scopes. To do this, on the "API permissions" tab in the "Application registration" node, the admin will need to click the "Grant admin consent for Directory" button. Once clicked, the status of the permissions should change from a yellow triangle to a green checkmark.
Admin Consent Flow
If the administrator is not a part of the same tenant, then you can provide them with an admin consent URL that will take them through the authorization steps in order to consent to the scopes. This link also works for admins in the same tenant if needed for ease of use.
The OAuth component supports this process via the ogtAdminConsent grant type. This flow requires that a redirect URI be set up to a valid localhost URI (see above). The component only requires that the client ID be set. If the administrator is on the same machine as the OAuth component, then the GetAuthorization method can be called to launch the browser and handle the redirect after the admin consents. If the admin consent application cannot be running on a machine accesible by the admin, then the GetAuthorizationURL method can be used to generate the URL directly. Once the admin consents, they will be redirected back to the localhost URI that is set in the URL. The redirect does not contain any necessary information but does contain any errors as well as the tenant ID of the administrator that just consented. The tenant ID is useful for creating the token server URL that will be needed later when authenticating the application but can be found in other places.Example: Launch Browser
Oauth oauth = new Oauth(); oauth.ClientProfile = OauthClientProfiles.ocpApplication; oauth.GrantType = OauthGrantTypes.ogtAdminConsent; oauth.ClientId = "CLIENT_ID"; oauth.WebServerPort = 7777; oauth.ReturnURL = "http://localhost:7777"; oauth.GetAuthorization(); string error = oauth.Config("Microsoft365AdminConsentError"); string errorDesc = oauth.Config("Microsoft365AdminConsentErrorDesc"); string tenantID = oauth.Config("Microsoft365AdminConsentTenant");Example: Provide URL Directly
Oauth oauth = new Oauth(); oauth.ClientProfile = OauthClientProfiles.ocpApplication; oauth.GrantType = OauthGrantTypes.ogtAdminConsent; oauth.ClientId = "CLIENT_ID"; oauth.WebServerPort = 7777; oauth.ReturnURL = "http://localhost:7777"; string authURL = oauth.GetAuthorizationURL();
If the application is using a legacy mail protocol (IMAP or POP), then the Office365 Exchange Administrator will also need to take steps to link the mailboxes to the application. Once the admin has consented to the API permissions of the application, the application will be added to the "Enterprise applications" node of the tenant (if the application is registered in the tenant, then it was added when the application was registered). This makes Azure aware of the application, but Office 365 Exchange also needs the application to be added there as well. To do this, in the tenant of the users whose mailbox the application needs access to, navigate to the "Enterprise applications" node. There, select the application and make note of the Application ID and the Object ID. It is important that these values are the ones from the "Enterprise applications" node rather than the "App registrations" node.
Next, the Exchange administrator will need to add a new service principal for the application. The following PowerShell cmdlets will connect the administrator to Exchange Online, create a new service principal, and then add the mailbox permission for the user to the newly created service principal. It is important to note that the Add-MailboxPermission cmdlet will need to be ran per mailbox (including shared mailboxes).
Install - Module - Name ExchangeOnlineManagement - allowprerelease Import - module ExchangeOnlineManagement Connect-ExchangeOnline -Organization TENANT_ID New-ServicePrincipal -AppId APPLICATION_ID -ServiceId OBJECT_ID Add-MailboxPermission -Identity EMAIL -User OBJECT_ID -AccessRights FullAccess
Once complete, Office365 Exchange should be aware of the application, enabling the use of the client credential grant flow.
Below are two examples of using the client credential grant type depending on the API and component you are using. The first example is using the internal OAuth support that the components in CloudKeys, CloudMail, and CloudStorage provide innately. The second example is using the OAuth component directly to get the access token, which is then supplied to the IMAP component to use for authentication.Example: Microsoft Graph
Office365 office365 = new Office365(); office365.OAuth.ClientProfile = OAuthClientProfiles.cocpApplication; office365.OAuth.GrantType = OAuthGrantTypes.cogtClientCredentials; office365.OAuth.ClientId = CLIENT_ID; office365.OAuth.ClientSecret = CLIENT_SECRET; office365.OAuth.ServerTokenURL = "https://login.microsoftonline.com/TENANT_ID/oauth2/v2.0/token"; office365.OAuth.AuthorizationScope = "https://graph.microsoft.com/.default"; office365.Authorize(); office365.Config("UserIDfirstname.lastname@example.org"); office365.MessageSubject = "I saw a Tree"; office365.MessageBodyContentType = "TEXT"; office365.MessageBodyContent = "It was in my back yard initially. It was still there when I last checked."; office365.MessageTo = "TreeLookOut@gmail.com"; office365.SendMail(True);Example: Legacy Mail API
Oauth oauth = new Oauth(); oauth.ClientProfile = OauthClientProfiles.ocpApplication; oauth.GrantType = OauthGrantTypes.ogtClientCredentials; oauth.ClientId = "CLIENT_ID"; oauth.ClientSecret = "CLIENT_SECRET"; oauth.ServerTokenURL = "https://login.microsoftonline.com/TENANT_ID/oauth2/v2.0/token"; oauth.AuthorizationScope = "https://outlook.office365.com/.default"; string authorization = oauth.GetAuthorization(); Imap imap = new Imap(); imap.AuthMechanism = ImapAuthMechanisms.amXOAUTH2; imap.Config("AuthorizationIdentity=" + authorization); imap.MailServer = "outlook.office365.com"; imap.User = "EMAIL"; imap.SSLStartMode = ImapSSLStartModes.sslImplicit; imap.MailPort = 993; imap.Connect();
When looking at the client credential grant type, it is important to consider the security and accessibility of your application. While it does reduce the amount of user interaction in the application, it does increase the ammount of work required for the administrators of the cloud environments. It is generally recommended by Microsoft to use other grant types if possible as they provide extra protections if the application is compromised through the use of delegated permissions. More information about the differences between delegated and application permissions can be found here.
We appreciate your feedback. If you have any questions, comments, or suggestions about this article please contact our support team at email@example.com.