Customization of auth providers and plugging in Kiota authproviders into Graph SDK

See original GitHub issue

Authentication Abstractions in Kiota:

interface AuthenticationProvider {
    authenticateRequest:void;
}
abstract class BaseBearerTokenAuthenticationProvider {
    public authenticateRequest{
        //
    }
    abstract public getAuthorizationToken();
}
class AzureIdentityAuthenticationProvider extends BaseBearerTokenAuthenticationProvider{
    public getAuthorizationToken(){
        // return the access token; 
    }
}

Authentication Abstractions in current Graph JS SDK:

class AuthenticationHandler {
    authProvider: AuthProvider
    middleware.execute() or authenticateRequest(){ 
        if(Graph Specific Condition){
            const token = authProvider.getAccessToken();
            appendToHeader("Authorization", token);
        }
        else {
            deleteAuthHeader();
        }
    }
}
class AuthProvider
{ 
    getAccessToken();
}

Currently the Graph JS SDK uses a composition pattern. The AuthenticationHandler which is a part of the middleware verifies if the request url is a Graph URL or a custom host passed by the user and appends the authorization headers.

Goal :

Reuse Kiota AuthProviders such as the AzureIdentityAuthenticationProvider class and authentication abstractions as is in Graph SDKs.

Limitations:

Adding the customizations: The authenticateRequest in BaseBearerTokenAuthenticationProvidershould append the authorization headers based on the custom conditions. Thereby, the custom logic should also get extended into the child classes such as the AzureIdentityAuthenticationProvider. This limits reusing the existing BaseBearerTokenAuthenticationProvider and the auth providers as is.

Solution:

  • Apply composition pattern in Kiota. Maintain separate classes, one with the authenticateRequest and one with the getAccesstoken. I suggest this as it promotes reuse of Kiota authorizaton abstractions and classes.

  • Mantain separate GraphBaseBearerTokenAuthenticationProvider and Graph AuthProviders which extends the former class.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:13 (12 by maintainers)

github_iconTop GitHub Comments

2reactions
baywetcommented, Jan 12, 2022

Encapsulation over inheritance, I like the suggestion 😃

So effectively we’d have

interface AuthenticationProvider { //This doesn't change and exists in Kiota today
    authenticateRequest: (request: RequestInformation) => Promise<void>;
}

interface AccesTokenProvider { // We'd add this interface definition in Kiota abstractions
   getAccessToken: (url: URL| string) => Promise<string>;
}

abstract class BaseBearerTokenAuthenticationProvider() {// already exist in Kiota
    constructor(public readonly accessTokenProvider: AccesTokenProvider ){}; // we're adding this constructor and field
    
    public authenticateRequest = async (request: RequestInformation) : Promise<void> => {} // already exists today, it'd call the authProvider instead of the abstract method

   // we'd remove the abstract method definition
}

// in each authentication package we'd have two things I'm going to take the example of Azure identity

export class AzureIdentityAuthenticationProvider extends BaseBearerTokenAuthenticationProvider {
    /**
     *
     */
    public constructor(credentials: TokenCredential, scopes: string[] = ['https://graph.microsoft.com/.default']) {
        super(new AzureIdentityAccessTokenProvider(credentials, scopes));
    }
}

export class AzureIdentityAccessTokenProvider implement AccessTokenProvider { // this is new 
    public constructor(private readonly credentials: TokenCredential, private readonly scopes: string[] = ['https://graph.microsoft.com/.default']) {
        if(!credentials) {
            throw new Error('parameter credentials cannot be null');
        }
        if(!scopes || scopes.length === 0) {
            throw new Error('scopes cannot be null or empty');
        }
    }

    public getAuthorizationToken = async (_: URL|string) : Promise<string> => {
        const result = await this.credentials.getToken(this.scopes);
        return result?.token ?? '';
    }
}

In terms of consumption the user would only have to do:

import Client from "Graph library";
import AzureIdentityAuthenticationProvider from "Kiota AuthProvider";

const graphClient = Client.init({
    authProvider: new AzureIdentityAuthenticationProvider(deviceCodeCredentials, scopes),
});

And the client could use the authentication provider as is for the fluent API or the access token provider for the existing arbitrary API. (by accessing the accessTokenProvider property on the BaseBearerTokenAuthenticationProvider)

Now, this adds a level of complexity but adds the advantage of making the providers reusable for both Kiota and the current JS SDK, (as well as other surfaces like MGT etc…)

@nikithauc did I capture properly what you were expressing? @andrueastman do you think we should apply that for all languages? I’m tempted to say yes for uniformity even if it means a bit more work. @sebastienlevert for the experience side of things and the impact on MGT.

1reaction
nikithauccommented, Jan 14, 2022

Should SPFx ā€œbreak somethingā€, we can major rev just the package for SPFx, no impact on other audiences.

@sebastienlevert This is something keep in mind and discuss about when considering the same version numbers for the packages.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Choose a Microsoft Graph authentication provider
Learn how to choose scenario-specific authentication providers for your application.
Read more >
Using authProvider with MS SDK for graph calls in C# - ...
As the authentication provider, set an async lambda // which uses the MSAL client to obtain an app-only access token to Microsoft Graph,Ā ......
Read more >
Untitled
iauthenticationprovider Welcome to Kiota Microsoft Learn Customization of auth providers and plugging in Kiota msgraph-sdk-python/authentication_samples.md atĀ ...
Read more >
Using custom SDK built with Microsoft Graph Kiota ... - YouTube
In this 13-minute developer-focused demo, Luis MaƱez shows how to use a Kiota generated client in an SPFx Teams webpart.
Read more >
How to use a Kiota client for a SharePoint framework API
The following snippet is getting an SPFx AadTokenProvider from the AadTokenProviderFactory. Then a custom SpfxAadAuthenticationProvider isĀ ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found