API Authentication: OAuth 2.0
Understand OAuth 2.0: secure delegation of access without sharing passwords.
A Simple Analogy
OAuth 2.0 is like valet parking. You don't give the valet your house key (password); you give them a limited valet key that only starts the car. They can't access your trunk or glove box. The valet key can be revoked without changing your house key.
What Is OAuth 2.0?
OAuth 2.0 is an authorization standard that allows users to grant third-party applications access to their resources without sharing passwords. It uses tokens instead of credentials.
Why Use OAuth 2.0?
- Security: Users never share passwords with apps
- Limited access: Grant specific permissions (scopes)
- Revocable: Easily disable access without changing password
- Delegation: Users authorize on identity provider
- Industry standard: Works with Google, GitHub, Microsoft
OAuth 2.0 Flow (Authorization Code)
1. User: "Log in with Google"
2. App: Redirects to Google login
3. Google: User authenticates and approves permissions
4. Google: Redirects back with authorization code
5. App backend: Exchanges code for access token
6. App: Uses token to access user data
Key Concepts
| Term | Meaning | |------|---------| | Resource Owner | User who owns the data | | Client | Your application | | Authorization Server | Google, GitHub (issues tokens) | | Resource Server | API with user data | | Scope | Permission level (read, write) | | Token | Credential proving authorization |
.NET Implementation
// Install: Microsoft.AspNetCore.Authentication.OAuth
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "GitHub";
})
.AddCookie("Cookies")
.AddOAuth("GitHub", options =>
{
options.ClientId = builder.Configuration["GitHub:ClientId"];
options.ClientSecret = builder.Configuration["GitHub:ClientSecret"];
options.CallbackPath = "/signin-github";
options.AuthorizationEndpoint = "https://github.com/login/oauth/authorize";
options.TokenEndpoint = "https://github.com/login/oauth/access_token";
options.UserInformationEndpoint = "https://api.github.com/user";
options.ClaimActions.MapJsonKey("urn:github:login", "login");
options.ClaimActions.MapJsonKey("urn:github:url", "html_url");
});
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
[Authorize]
[Route("api/[controller]")]
public class ProfileController : ControllerBase
{
[HttpGet]
public IActionResult GetProfile()
{
var login = User.FindFirst("urn:github:login")?.Value;
return Ok(new { github_login = login });
}
}
Practical Example
// Using HttpClient to call API with OAuth token
public class GitHubService
{
private readonly HttpClient _httpClient;
private readonly IHttpContextAccessor _httpContextAccessor;
public async Task<List<Repository>> GetUserRepositoriesAsync()
{
// Get token from authentication
var token = await _httpContextAccessor.HttpContext
.GetTokenAsync("access_token");
_httpClient.DefaultRequestHeaders.Authorization =
new("Bearer", token);
var response = await _httpClient.GetAsync("https://api.github.com/user/repos");
var json = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<List<Repository>>(json);
}
}
Common Scopes
GitHub:
- repo: Access to repositories
- gist: Access to gists
- user: Access to user profile
Google:
- openid: Basic identity
- profile: User profile information
- email: User email address
Best Practices
- Use HTTPS: Always secure communication
- Validate tokens: Verify signature and expiration
- Scopes: Request minimal necessary permissions
- State parameter: Prevent CSRF attacks
- Refresh tokens: Rotate long-lived credentials
Related Concepts to Explore
- OpenID Connect (built on OAuth 2.0)
- PKCE (for mobile apps)
- Token refresh strategies
- Multiple OAuth providers
- Custom authorization servers
Summary
OAuth 2.0 enables secure, delegated access without passwords. Use it for social login and API authentication to improve user experience and security.