Establishing OAuth 2.0 Authentication to SharePoint Online REST Services in .NET
Introduction into how to use OAuth 2.0 to authenticate to SharePoint Online
In this article, I will share how to authenticate with OAuth 2.0 on Office 365’s SharePoint Online platform. The process includes registration of an app on Entra ID with certificate authentication, obtaining an OAuth 2.0 access token via .NET, and authenticating to SharePoint Online’s REST Services using the access token.
- Register App in Entra ID as Non-Interactive with Certificate Authentication
- Get an OAuth 2.0 Access Token in .NET
- Authenticate to SharePoint Online REST Services with the Access Token
By the end of this article, you should have a better understanding of how to authenticate to SharePoint Online REST Services via OAuth 2.0.
Background
Microsoft is currently in the process of disabling legacy authentication (username and password authentication) for its Office 365 services.
This step is taken to improve security, as legacy authentication is vulnerable to password attacks. It's not safe.
Microsoft requires using modern authentication protocols, especially OAuth 2.0. By implementing OAuth 2.0, SharePoint REST Services can be continuously used while staying safe! Wow!
Idea
The first step for OAuth 2.0 on SharePoint Online’s REST Service is to register an application. The application registration is to be done on Entra ID and requires certificate authentication, as it is required to use certificate credentials on the SharePoint Online REST endpoints.
SharePoint Online REST API Authentication In POSTMAN — SharePoint Stack Exchange
After administrative tasks are completed, including registering the app in Entra ID, we can use the .NET library provided by Microsoft to authenticate.
Microsoft.Identity.Client Namespace — Microsoft Authentication Library for .NET | Microsoft Learn
Once the access token is obtained, it can be used as a bearer to authorize all subsequent API requests
Implementation
1. Register App in Entra ID with Certificate Authentication
To start with authentication using OAuth 2.0 on Office 365’s SharePoint Online platform, the first step is to create an application registration.
Please note the following requirements:
(1) Ensure that the app is non-interactive. That means that the app operates in the background, without any user interaction, and does not require additional user credentials to be used.
(2) Use certificate-based authentication for the registration. SharePoint Online REST services only support authentication with certificates.
For a quick start guide on how to register an app with Entra ID, please follow this link:
2. Get an OAuth 2.0 Access Token in .NET
Implementing an OAuth 2.0 Credentials POCO (optional)
Before getting into implementation details, we can create a POCO (Plain Old C# Object) class to gain an overview of the data used for OAuth2.0-based authentication.
For authentification, the following fields are necessary:
- AppId
- TenantId
- ClientSecret (might be skippable, depending on tenant config)
- Certificate
///<summary>
/// Example class for holding oAuth authentification data
///</summary>
public class AuthDataSetOAUTH
{
public string AppName { get; set; } //optional, but nice for keeping an overview
public string AppId { get; set; }
public string ObjectId { get; set; }
public string TenantId { get; set; }
public SecureString ClientSecret{ get; set; }
public X509Certificate2 Certificate { get; set; }
}
Building the ConfidentialClientApplication
To implement OAuth 2.0 authentication on Office 365’s SharePoint Online platform, MSAL.NET provides a set of tools and libraries.
Confidential client applications are one type of application that can be used with MSAL.NET.
For our purposes, the client app registration is represented as a confidential client application.
ConfidentialClientApplicationBuilder
.Create(authData.AppId)
.WithClientId(authData.AppId)
.WithClientSecret(authData.ClientSecret)
.WithCertificate(authData.Certificate) //crucial for authentificaiton with certificate
.WithAuthority($"https://login.microsoftonline.com/{authData.TenantId}")
.WithTenantId(authData.TenantId)
.Build();
3. Authentification Logic
The following example is a class that demonstrates the implementation of an OAuth 2.0 flow.
This class contains methods to acquire an authentication token securely. The _BuildConfidentialClient method creates a confidential client application that includes the required authentication data, including the app ID, client secret, and tenant ID. It then builds this client application and returns it for further use.
The BuildAuthProviderOAuth method leverages the _BuildConfidentialClient method to check if the specified authentication token is valid. If it is not, it creates and executes a new authentication token request. It uses the AcquireTokenForClient method with a scopes parameter to specify the permissions that are required to access SharePoint resources. The obtained AuthenticationResult is then returned.
The _RequestAuthTokenOrRenew method is designed to either request a new token or reuse an existing one if it is still valid. It creates a new instance of the OAuthFlow class, ensuring that the authentication token is obtained from a valid instance. It then checks if the stored authentication result is valid and has not expired. If it has expired, it renews the authentication token by calling the BuildAuthProviderOAuth method, which returns a new access token.
/// <summary>
/// Implementation of a very basic token acquiring flow in OAuth 2.0 for demo purposes
/// </summary>
public class OAuthFlow
{
/// <summary>
/// Building Client for the OAuth Flow
/// </summary>
/// <param name="authData"></param>
/// <returns></returns>
private IConfidentialClientApplication _BuildConfidentialClient(AuthDataSetOAUTH authData)
{
return ConfidentialClientApplicationBuilder
.Create(authData.AppId)
.WithClientId(authData.AppId)
.WithClientSecret(SecurePasswordHelper.SecureStringToString(authData.ClientSecret))
.WithCertificate(authData.Certificate)
.WithAuthority($"https://login.microsoftonline.com/{authData.TenantId}")
.WithTenantId(authData.TenantId)
.Build();
}
/// <summary>
/// Aquiring an authentification token to be used in standardized OAuth 2.0 Type of authentification flows
/// </summary>
/// <param name="authData"></param>
/// <param name="uri"></param>
/// <returns></returns>
public AuthenticationResult BuildAuthProviderOAuth(AuthDataSetOAUTH authData, string uri = "contoso.sharepoint.com")
{
IConfidentialClientApplication appAuth = _BuildConfidentialClient(authData);
string[] scopes = new string[] { $"https://{uri}/.default" };
return appAuth
.AcquireTokenForClient(scopes)
.ExecuteAsync().Result;
}
/// <summary>
/// Function for either requesting a new token or reusing an existing one
/// </summary>
/// <param name="authData"></param>
/// <returns></returns>
public static AuthenticationResult _RequestAuthTokenOrRenew(AuthDataSetOAUTH authData)
{
OAuthFlowoAuthAuthentificationFlow = new OAuthFlow();
if (_authResult == null)
_authResult = OAuthFlow.BuildAuthProviderOAuth(authData);
//if close to expiration, generate a new token
TimeSpan timeDifference = DateTimeOffset.Now - _authResult.ExpiresOn;
if (timeDifference.Duration() < TimeSpan.FromMinutes(10))
_authResult = OAuthFlow.BuildAuthProviderOAuth(authData);
return _authResult;
}
}
3. Authentificate to SharePoint Online REST Services with the Access Token
In this example, the ClientContext class of the Microsoft.SharePoint.Client namespace is utilized to access SharePoint REST Services. This class is designed to enable developers to communicate with SharePoint remotely and perform operations such as CRUD operations on SharePoint lists and libraries.
The _BuildClientContextOAuth method in the example creates a ClientContext variable with the specified SharePoint site URL as an argument. It also includes the application name, which is used to identify the client application when communicating with SharePoint.
The unique characteristic of this example is that the ClientContext variable is configured to use OAuth 2.0 authentication. The ExecutingWebRequest event of the ClientContext class is used to attach a specific callback function that sets the required authentication token to the web request's header. The AccessToken property of the AuthenticationResult is obtained from the OAuthAuthentificationFlow._RequestAuthTokenOrRenew method and is added to the web request header to authenticate and authorize the request.
Using the ClientContext class enables developers to make secure, authenticated calls to SharePoint's REST service. By coupling this implementation with OAuth 2.0 authentication, developers can ensure that their applications are secure while still being able to access SharePoint's resources with the Microsoft.SharePoint.Client library.
/// <summary>
/// Constructs an connection of the oauth typus
/// </summary>
/// <returns></returns>
public ClientContext _BuildClientContextOAuth(string spuri, string appname, AuthDataSetOAUTH authData)
{
var context = new ClientContext(spuri)
{
ApplicationName = appname,
AuthenticationMode = ClientAuthenticationMode.Default,
};
context.ExecutingWebRequest += (s, e) =>
{
string token = OAuthAuthentificationFlow._RequestAuthTokenOrRenew(authData).AccessToken;
e.WebRequestExecutor.RequestHeaders["Authorization"] = $"Bearer {token}";
};
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
return context;
}
Comments