CSharp/SPO.Samples/SPO.ModernAuthentication/Helpers/ServicePrincipalAuthenticationManager.cs
/// <summary>
/// Method to Ensure Access Token Async.
/// </summary>
/// <param name="resourceUri">Resource Uri.</param>
/// <param name="tenantId">Tenant Id.</param>
/// <param name="clientId">Client Id.</param>
/// <param name="clientCertificate">Client Certificate.</param>
/// <returns>Access Token.</returns>
Method to Ensure Access Token Async.
Method to Ensure Access Token Async .
public async Task<string> EnsureAccessTokenAsync(Uri resourceUri, string tenantId, string clientId, X509Certificate2 clientCertificate)
        {
            string accessTokenFromCache = TokenFromCache(resourceUri, this.tokenCache);
            if (accessTokenFromCache == null)
            {
                await SemaphoreSlimTokens.WaitAsync().ConfigureAwait(false);
                try
                {
                    string accessToken = await this.AcquireTokenAsync(resourceUri, tenantId, clientId, clientCertificate).ConfigureAwait(false);
                    Console.WriteLine($"Successfully requested new access token resource {resourceUri.DnsSafeHost} for user {clientId}");
                    AddTokenToCache(resourceUri, this.tokenCache, accessToken);
                    this.tokenResetEvent = new AutoResetEvent(false);
                    TokenWaitInfo wi = new TokenWaitInfo();
                    wi.Handle = ThreadPool.RegisterWaitForSingleObject(
                        this.tokenResetEvent,
                        async (state, timedOut) =>
                        {
                            if (!timedOut)
                            {
                                TokenWaitInfo internalWaitToken = (TokenWaitInfo)state;
                                if (internalWaitToken.Handle != null)
                                {
                                    internalWaitToken.Handle.Unregister(null);
                                }
                            }
                            else
                            {
                                try
                                {
                                    await SemaphoreSlimTokens.WaitAsync().ConfigureAwait(false);
                                    RemoveTokenFromCache(resourceUri, this.tokenCache);
                                    Console.WriteLine($"Cached token for resource {resourceUri.DnsSafeHost} and user {clientId} expired");
                                }
                                catch (Exception ex)
                                {
                                    Console.WriteLine($"Something went wrong during cache token invalidation: {ex.Message}");
                                    RemoveTokenFromCache(resourceUri, this.tokenCache);
                                }
                                finally
                                {
                                    SemaphoreSlimTokens.Release();
                                }
                            }
                        },
                        wi,
                        (uint)CalculateThreadSleep(accessToken).TotalMilliseconds,
                        true);
                    return accessToken;
                }
                finally
                {
                    SemaphoreSlimTokens.Release();
                }
            }
            else
            {
                Console.WriteLine($"Returning token from cache for resource {resourceUri.DnsSafeHost} and user {clientId}");
                return accessTokenFromCache;
            }
        }
public async Task < string > EnsureAccessTokenAsync ( Uri resourceUri , string tenantId , string clientId , X509Certificate2 clientCertificate ) { string accessTokenFromCache = TokenFromCache ( resourceUri , this . tokenCache ) ; if ( accessTokenFromCache == null ) { await SemaphoreSlimTokens . WaitAsync ( ) . ConfigureAwait ( false ) ; try { string accessToken = await this . AcquireTokenAsync ( resourceUri , tenantId , clientId , clientCertificate ) . ConfigureAwait ( false ) ; Console . WriteLine ( $" Successfully requested new access token resource  { resourceUri . DnsSafeHost }  for user  { clientId } " ) ; AddTokenToCache ( resourceUri , this . tokenCache , accessToken ) ; this . tokenResetEvent = new AutoResetEvent ( false ) ; TokenWaitInfo wi = new TokenWaitInfo ( ) ; wi . Handle = ThreadPool . RegisterWaitForSingleObject ( this . tokenResetEvent , async ( state , timedOut ) => { if ( ! timedOut ) { TokenWaitInfo internalWaitToken = ( TokenWaitInfo ) state ; if ( internalWaitToken . Handle != null ) { internalWaitToken . Handle . Unregister ( null ) ; } } else { try { await SemaphoreSlimTokens . WaitAsync ( ) . ConfigureAwait ( false ) ; RemoveTokenFromCache ( resourceUri , this . tokenCache ) ; Console . WriteLine ( $" Cached token for resource  { resourceUri . DnsSafeHost }  and user  { clientId }  expired " ) ; } catch ( Exception ex ) { Console . WriteLine ( $" Something went wrong during cache token invalidation:  { ex . Message } " ) ; RemoveTokenFromCache ( resourceUri , this . tokenCache ) ; } finally { SemaphoreSlimTokens . Release ( ) ; } } } , wi , ( uint ) CalculateThreadSleep ( accessToken ) . TotalMilliseconds , true ) ; return accessToken ; } finally { SemaphoreSlimTokens . Release ( ) ; } } else { Console . WriteLine ( $" Returning token from cache for resource  { resourceUri . DnsSafeHost }  and user  { clientId } " ) ; return accessTokenFromCache ; } }
Method to Ensure Access Token Async.
Method to Ensure Access Token Async .
// No async methods are allowed in a lock section // Register a thread to invalidate the access token once's it's expired // Take a lock to ensure no other threads are updating the SharePoint Access token at this time
None
resourceUri
Uri
None
tenantId
string
None
clientId
string
None
clientCertificate
X509Certificate2
None