Search code examples
c#oauth-2.0asp.net-mvc-5azure-active-directorymicrosoft-graph-api

Microsoft Graph - Resource Owner Password Credentials alternative


Here's the context:

  • I have an external application (let's call it EA) which contain users. Each user is able to login using an email and a password.

  • I have an Azure Active Directory containg users. They are exactly the same users as in the EA.

Here's the scenario:

  • The user login in the EA. In the EA, the user can create an online Microsoft Teams meeting using the Graph API (The meeting creation is already done and working).

Here's the problem:

  • The user need to manually login again in the Azure Active Directory in order to create the online Microsoft Teams meeting, even though he is logged in the EA.

Here's my ugly fix:

  • I used the Resource Owner Password Credentials to login the user again in the backend. The way I did it is the following: when the user try to create a online meeting, he is prompted to enter is password again in an HTML form. The form leads eventually to this method, recovering the Azure Active Directory access token:
    public async Task<string> GetTokenUser(string email, string password) 
    {
        string token = null;
        var clientID = "<ApplicationClientID>";
        var secret = "<ApplicationSecret>";
        var tenantID = HttpUtility.UrlEncode("<TenantDomain>");
        var resource = HttpUtility.UrlEncode("https://graph.microsoft.com");
        email= HttpUtility.UrlEncode(email);
        password= HttpUtility.UrlEncode(password);

        using (HttpClient client = new HttpClient())
        {
            var tokenEndpoint = @"https://login.windows.net/" + tenantID + "/oauth2/token";
            var accept = "application/json";

            client.DefaultRequestHeaders.Add("Accept", accept);
            string postBody = @"resource=" + resource + @"
                                &client_id=" + clientID + @"
                                &client_secret=" + secret  + @"
                                &grant_type=password
                                &username=" + email + @"
                                &password=" + password + "&scope=openid";

            using (var response = await client.PostAsync(tokenEndpoint, new StringContent(postBody, Encoding.UTF8, "application/x-www-form-urlencoded")))
            {
                if (response.IsSuccessStatusCode)
                {
                    var jsonresult = JObject.Parse(await response.Content.ReadAsStringAsync());
                    token = (string)jsonresult["access_token"];
                }
            }
        }

        return token;
    }

Here's what I need:

  • I need to find a better way to login the user in Azure Active Directory without having to prompt the password again. Is there any way to tell Azure Active Directory that X user is logged in by email without having to send a plain text password?

Important note: I have absolutely no preference on how this could be achieved, as long as it works and it is reliable.

Edit 1: Typo in code


Solution

  • Azure AD authentication is necessary if you want to access Microsoft Graph.

    Create onlineMeeting only supports Delegated permission, which means you have to follow Get access on behalf of a user to get the access token.

    So if you don't want to use ROPC flow, you need to integrate AAD authorization sign in into your project.

    Please follow this document to learn how to do it.