Right Click Is Disabled...

OAuth 2.0 Using Asp .Net Core

What Is OAuth?

OAuth, which stands for “Open Authorization,” allows third-party services to exchange your information without you having to give away your password.

The OAuth (open authorization) protocol was developed by the Internet Engineering Task Force and enables secure delegated access. It lets an application access a resource that is controlled by someone else (end user). This kind of access requires Tokens, which represent delegated right of access.

It’s a process through which an application or website can access private data from another website. It provides applications the ability for “secure designated access.” For example, you can tell Google that it’s OK for abc.com to access your google account or contact without having to give abc.com your google password.

OAuth never share password data but instead uses authorization tokens to prove an identity between consumers and service providers. OAuth is an authentication protocol that allows you to approve one application interacting with another on your behalf without giving away your password.

The Authorization Code Flow

Flow

The client redirects the user to the authorization server having the following parameters in the query string.

Step 1

  • response_type having the value code
  • client_id having the client identifier
  • redirect_uri having the client redirect URI.
  • scope a space-delimited list of scopes
  • state having a random string

After successful authentication, the user will be redirected to the Consent screen where he needs to provide consent to abc.com to access the account detail.

Authorization code is generated by the authorization server and sent back to the client with redirect Uri.

Step 2

The client will now send a POST request to the authorization server with the following parameters:

  • Grant_type having the value of authorization_code
  • Client_id having the client identifier
  • Client_secret having the client secret
  • Redirect_uri having the same redirect URI the user redirected back.
  • Code having the authorization code from the query string

In the entire flow, the access token is never exposed to a web browser.
The client will ask the user for their authorization credentials (usually a username and password). The client then sends a POST request with following body parameters to the authorization server:

  • Grant_type having the value password
  • Client_id having the client’s ID
  • Client_secret having the client’s secret
  • Scope having a space-delimited list of requested scope permissions.
  • Username having a user’s username
  • Password having a user’s password

Client Credentials Grant

Using this flow the client can request an access token using only its client credentials (or other supported means of authentication). 

Asp .Net OAuth Using Github Example

->First Open GitHub  then Click on Profile -> settings -> Developer Setting ->OAuth Apps 

Display Below Screen After that and click on New OAuth App

Filling details for register a new OAuth application And then Click Register application.

If you have completed register successfully then showing below OAuthWithGitHub screen. Here show your Client Id and Client Secrets. Click on Generate a new Client Secrets For generating your own secrets.

Now Next Step is Create Asp .Net Core App

Here we need some packages for more process. so keep install below following packages.

AspNet.Security.OAuth.GitHub
Microsoft.AspNetCore.Authentication.Cookies
Microsoft.AspNetCore.Authentication.OAuth

launchSetting.json File

{
    "GitHub": {
        "ClientId": "0aa85390cf6d6c0018bd",
        "ClientSecret": "411661edf9968c89390b21f486800a26cd153a54"
    },
    "linkedin": {
        "clientid": "75xcbb4icwltx3",
        "clientSecret": "giSng0gfq81DTUzZ"
    },
    "Logging": {
        "LogLevel": {
            "Default": "Information",
            "Microsoft": "Warning",
            "Microsoft.Hosting.Lifetime": "Information"
        }
    },
    "AllowedHosts": "*"
}

Set port number given in github oauth Registration and give Secure Connection.

Startup.cs File

using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace OAuthApplication
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
        private IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            // Step 1. Add Authentication Mechanisms
            services.AddAuthentication(o =>
            {
                o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            })
            .AddCookie(o =>
            {
                // set the path for the authentication challenge
                o.LoginPath = "/signin";
                
                // set the path for the sign out
                o.LogoutPath = "/signout";
            })
            .AddGitHub(o =>
            {
                 o.ClientId = Configuration["github:clientId"];
                 o.ClientSecret = Configuration["github:clientSecret"];
                 o.CallbackPath = "/signin-github";
                 // Grants access to read a user's profile data.
                 o.Scope.Add("read:user");
                 // Optional
                 // if you need an access token to call GitHub Apis
                 o.Events.OnCreatingTicket += context =>
                 {
                     if (context.AccessToken is { })
                     {
                         context.Identity?.AddClaim(new Claim("access_token", context.AccessToken));
                     }
                     return Task.CompletedTask;
                 };
            });
            services.AddRazorPages();
        }
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                app.UseHsts();
            }
            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseRouting();
            
            // 2. add Authentication and Authorization Middleware
            app.UseAuthentication();
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();
                // 3. Sign out Endpoint
                // go to ./Pages/Signin.cshtml for 4.
                endpoints.MapGet("/signout", async ctx =>
                {
                    await ctx.SignOutAsync(
                     CookieAuthenticationDefaults.AuthenticationScheme,
                    new AuthenticationProperties
                    {
                        RedirectUri = "/"
                    });
                });
            });
        }
    }
}

Here You can Acces user Access Token if you needed.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.DependencyInjection;
namespace OAuthApplication.Pages
{
    public class Signin : PageModel
    {
        public IEnumerable<AuthenticationScheme> Schemes { get; set; }
        [BindProperty(SupportsGet = true)]
        public string ReturnUrl { get; set; }
        public async Task OnGet()
        {
            Schemes = await GetExternalProvidersAsync(HttpContext);
        }
        public async Task<IActionResult> OnPost([FromForm] string provider)
        {
            if (string.IsNullOrWhiteSpace(provider))
            {
                return BadRequest();
            }
            return await IsProviderSupportedAsync(HttpContext, provider) is false
             ? BadRequest()
             : Challenge(new AuthenticationProperties
             {
                 RedirectUri = Url.IsLocalUrl(ReturnUrl) ? ReturnUrl : "/"
             }, provider);
        }

       private static async Task<AuthenticationScheme[]> GetExternalProvidersAsync(HttpContext context)
        {
            var schemes = context.RequestServices.GetRequiredService<IAuthenticationSchemeProvider>();
            return (await schemes.GetAllSchemesAsync())
             .Where(scheme => !string.IsNullOrEmpty(scheme.DisplayName))
             .ToArray();
        }

        private static async Task<bool> IsProviderSupportedAsync(HttpContext context, string provider) =>
        (await GetExternalProvidersAsync(context))
        .Any(scheme => string.Equals(scheme.Name, provider, StringComparison.OrdinalIgnoreCase));
    }
}

Write Above Code in Signin.Cshtml.cs File to set retunUrl this file works like Controller Define Your methods. 

@page
@model OAuthApplication.Pages.Signin
@{
}
<div class="jumbotron">
    <h1>Authentication</h1>
    <p class="lead text-left">Sign in using one of these external providers:</p>
    @foreach (var scheme in Model.Schemes.OrderBy(p => p.DisplayName))
    {
        <form asp-page="SignIn" method="post">
            <input type="hidden" name="Provider" value="@scheme.Name" />
            <input type="hidden" name="ReturnUrl" value="@Model.ReturnUrl" />
            <button class="btn btn-lg btn-success m-1" type="submit">
                Sign in using @scheme.DisplayName
            </button>
        </form>
    }
</div>

Above Code is Signin.Cshtml file here fetach the user details and redirect our website. 

After that Display User Data in our Website.

Below Code is Account.Cshtml.Cs File To list Out User data.

using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.RazorPages;
using OAuthApplication.Models;
using Octokit;
namespace OAuthApplication.Pages
{
    [Authorize]
    public class Account : PageModel
    {
        public async Task OnGet()
        {
            // We are reading claims that were
            //    supplied from our OpenID provider
            Claims = User.Claims.ToList();
            // From GitHub
            if (User.AccessToken() is { } accessToken)
            {
                var client = new GitHubClient(new ProductHeaderValue("test"))
                {
                    Credentials = new Credentials(accessToken)
                };
                GitHubUser = await client.User.Get(User.Identity?.Name);
            }
        }
        public User GitHubUser { get; set; }
        public List<Claim> Claims { get; set; }
    }
}

 This Is Account.CsHtml File Code.

@page
@model OAuthApplication.Pages.Account
@{
    var Uri = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/";
}
<h2>User Claims</h2>
<table class="table table-bordered table-striped">
    <thead>
    <tr>
        <th>Type</th>
        <th>Value</th>
    </tr>
    </thead>
    <tbody>
    @foreach (var claim in Model.Claims)
    {
        <tr>
            <td>@claim.Type.Replace(Uri, string.Empty)</td>
            <td>
                @if (claim.Type == "access_token")
                {
                    <div class="input-group mb-3">
                        <div class="input-group-prepend">
                            <span class="input-group-text" id="access-token">
                                &#128065;
                            </span>
                        </div>
                        <input id="access-token" 
                               type="password" value="@claim.Value" 
                               onclick="toggleVisibility(this)" 
                               class="form-control" 
                               title="click me to reveal password" />
                    </div>
                }
                else
                {
                    @claim.Value                    
                }
            </td>
        </tr>
    }
    </tbody>
</table>
@if (Model.GitHubUser is {})
{
    <h2>GitHub Octokit Response</h2>
    <table class="table table-bordered table-striped">
        <thead>
        <tr>
            <th>Type</th>
            <th>Value</th>
        </tr>
        </thead>
        <tbody>
        <tr>
            <td>@nameof(Model.GitHubUser.Bio)</td>
            <td>@Model.GitHubUser.Bio</td>
        </tr>
        <tr>
            <td>@nameof(Model.GitHubUser.Location)</td>
            <td>@Model.GitHubUser.Location</td>
        </tr>
        <tr>
            <td>@nameof(Model.GitHubUser.AvatarUrl)</td>
            <td>
                <img src="@Model.GitHubUser.AvatarUrl" alt="avatar"/>
            </td>
        </tr>
        </tbody>
    </table>
}

Source code

Source code for this sample is available on GitHub at https://github.com/xtsofttech/OAuthApplication

Share On

Leave a Comment

Your email address will not be published. Required fields are marked *