- Bitsbyte
- Posts
- OpenID Connect (OIDC) and OAuth 2.0
OpenID Connect (OIDC) and OAuth 2.0
Protocols that work together to provide authentication and authorization.
Overview of OpenID Connect and OAuth 2.0
OpenID Connect (OIDC) is an authentication layer built on top of OAuth 2.0, allowing clients to verify the identity of users based on the authentication performed by an authorization server. OAuth 2.0 is a protocol that allows third-party applications to obtain limited access to an HTTP service, either on behalf of a resource owner or by allowing the application to obtain access on its own behalf.
Key Components
Authorization Server: Issues access tokens after authenticating users.
Resource Server: Hosts the protected resources and validates access tokens.
Client Application: The application requesting access to the user's resources.
Setting Up the Backend with .NET Core
Step 1: Create a New ASP.NET Core Project
Use the following command to create a new ASP.NET Core Web API project:
dotnet new webapi -n AuthDemo
cd AuthDemo
Step 2: Install Required Packages
Add the necessary NuGet packages for authentication:
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
dotnet add package Microsoft.IdentityModel.Tokens
Step 3: Configure Authentication in Startup.cs
In your Startup.cs
, configure JWT authentication:
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "YourIssuer",
ValidAudience = "YourAudience",
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("YourSecretKey"))
};
});
services.AddControllers();
}
Step 4: Create a Controller for Authentication
Create an AuthController.cs
to handle user login and token generation:
[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase
{
[HttpPost("login")]
public IActionResult Login([FromBody] LoginModel model)
{
// Validate user credentials (this is just an example)
if (model.Username == "test" && model.Password == "password")
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.UTF8.GetBytes("YourSecretKey");
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]
{
new Claim(ClaimTypes.Name, model.Username)
}),
Expires = DateTime.UtcNow.AddHours(1),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return Ok(new { Token = tokenHandler.WriteToken(token) });
}
return Unauthorized();
}
}
Setting Up the Frontend with React.js
Step 1: Create a New React Application
Use Create React App to set up your frontend:
npx create-react-app auth-demo-frontend
cd auth-demo-frontend
Step 2: Install Axios for HTTP Requests
Install Axios for making API calls:
npm install axios
Step 3: Create a Login Component
Create a Login.js
component to handle user login:
import React, { useState } from 'react';
import axios from 'axios';
const Login = () => {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const handleLogin = async () => {
const response = await axios.post('http://localhost:5000/api/auth/login', { username, password });
localStorage.setItem('token', response.data.token);
};
return (
<div>
<input type="text" onChange={(e) => setUsername(e.target.value)} placeholder="Username" />
<input type="password" onChange={(e) => setPassword(e.target.value)} placeholder="Password" />
<button onClick={handleLogin}>Login</button>
</div>
);
};
export default Login;
Step 4: Protect Routes Using JWT
You can protect certain routes by checking if the JWT is stored in local storage. Here’s an example of how you might implement this in a ProtectedRoute.js
component:
import React from 'react';
import { Navigate } from 'react-router-dom';
const ProtectedRoute = ({ children }) => {
const token = localStorage.getItem('token');
if (!token) {
return <Navigate to="/" />;
}
return children;
};
export default ProtectedRoute;
Conclusion
This setup provides a basic implementation of OpenID Connect and OAuth 2.0 using .NET Core for the backend and React.js for the frontend, leveraging JWTs for user authentication. By following these steps, you can create a secure application that verifies user identities effectively.
For further enhancements, consider integrating with an identity provider like Keycloak or Azure AD for more robust authentication features and user management capabilities.