This code example indicates how to build an app that supports Microsoft account OAuth authentication.

Before coding, we gonna create an app in your Azure portal first. https://portal.azure.com

The name is your app's display name. Select your app can access accounts in any organization and personal Microsoft account. As for the redirect URI, it must be your server redirect back address. For example:

https://gateway.aiursoft.com/debug

After creating your app, copy your application id here:

And create a secret here.

Don't forget to copy your secret value.

Running the following code requires some classes like AiurUrl and Aiursoft.XelNaga.Services.HTTPService. To get it, run:

$ dotnet add package Aiursoft.XelNaga

To authenticate the user, we need to redirect him to the Microsoft login portal. Copy the following code:

        public string GetBindRedirectLink()
        {
            return new AiurUrl("https://login.microsoftonline.com", $"/{_tenant}/oauth2/v2.0/authorize", new MicrosoftAuthAddressModel
            {
                ClientId = _clientId,
                RedirectUri = "https://gateway.aiursoft.com/debug",
                ResponseType = "code",
                Scope = "user.read",
                State = ""
            }).ToString();
        }

    public class MicrosoftAuthAddressModel
    {
        [FromQuery(Name = "client_id")]
        public string ClientId { get; set; }
        [FromQuery(Name = "redirect_uri")]
        public string RedirectUri { get; set; }
        [FromQuery(Name = "state")]
        public string State { get; set; }
        [FromQuery(Name = "scope")]
        public string Scope { get; set; }
        [FromQuery(Name = "response_type")]
        public string ResponseType { get; set; }
    }

Just return a redirect result to the browser and the redirect URL is from the GetBindRedirectLink() function.

When the user has successfully signed in his account, he will be redirected back to your RedirectUri. With a code. The code is what we need.

From the code, you can call the GetUserDetail() method to get the user's profile.

        public async Task<IUserDetail> GetUserDetail(string code)
        {
            var token = await GetAccessToken(_clientId, _clientSecret, code);
            return await GetUserInfo(token);
        }

The _clientId and _clientSecret is what you copied when you created the app.

        private async Task<string> GetAccessToken(string clientId, string clientSecret, string code)
        {
            var apiAddress = "https://login.microsoftonline.com" + $"/{_tenant}/oauth2/v2.0/token";
            var url = new AiurUrl(apiAddress, new { });
            var form = new AiurUrl(string.Empty, new MicrosoftAccessTokenAddressModel
            {
                ClientId = clientId,
                ClientSecret = clientSecret,
                Code = code,
                Scope = "user.read",
                RedirectUri = "https://gateway.aiursoft.com/debug",
                GrantType = "authorization_code"
            });
            try
            {
                var json = await _http.Post(url, form, false);
                var response = JsonConvert.DeserializeObject<AccessTokenResponse>(json);
                if (string.IsNullOrWhiteSpace(response.AccessToken))
                {
                    throw new AiurAPIModelException(ErrorType.Unauthorized, "Invalid Microsoft crenditial");
                }
                return response.AccessToken;
            }
            catch (WebException)
            {
                throw new AiurAPIModelException(ErrorType.Unauthorized, "Invalid Microsoft API response");
            }
        }

    public class MicrosoftAccessTokenAddressModel
    {
        [FromQuery(Name = "client_id")]
        public string ClientId { get; set; }
        [FromQuery(Name = "client_secret")]
        public string ClientSecret { get; set; }
        [FromQuery(Name = "code")]
        public string Code { get; set; }
        [FromQuery(Name = "scope")]
        public string Scope { get; set; }
        [FromQuery(Name = "grant_type")]
        public string GrantType { get; set; }
        [FromQuery(Name = "redirect_uri")]
        public string RedirectUri { get; set; }
    }

The GetAccessToken() method helps you get a valid access token so you can use it to download the user profile.

When you have the access token, just call the GetUserInfo(). Right here we gonna call the graph API to get the current user info.

        private async Task<MicrosoftUserDetail> GetUserInfo(string accessToken)
        {
            var apiAddress = "https://graph.microsoft.com/v1.0/me";
            var request = new HttpRequestMessage(HttpMethod.Get, apiAddress);

            request.Headers.Add("Authorization", $"Bearer {accessToken}");
            var response = await _client.SendAsync(request);
            if (response.IsSuccessStatusCode)
            {
                var json = await response.Content.ReadAsStringAsync();
                var user = JsonConvert.DeserializeObject<MicrosoftUserDetail>(json);
                return user;
            }
            else
            {
                throw new WebException(response.ReasonPhrase);
            }
        }

The returned user is an instance of MicrosoftUserDetail.

    public class MicrosoftUserDetail : IUserDetail
    {
        [JsonProperty("id")]
        public string Id { get; set; }
        [JsonProperty("displayName")]
        public string DisplayName{ get; set; }
        [JsonProperty("userPrincipalName")]
        public string UserPrincipalName { get; set; }
        [JsonProperty("jobTitle")]
        public string JobTitle{ get; set; }
    }

The Id is unique. Use it to identify your user.

Finally, build a custom web page, and your app is ready to go.

Source code is here:

https://github.com/AiursoftWeb/Nexus/blob/master/Pylon/Services/Authentication/ToMicrosoftServer/MicrosoftService.cs