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">
👁
</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