✨ Support OIDC
This commit is contained in:
148
DysonNetwork.Sphere/Pages/Auth/Authorize.cshtml.cs
Normal file
148
DysonNetwork.Sphere/Pages/Auth/Authorize.cshtml.cs
Normal file
@ -0,0 +1,148 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using DysonNetwork.Sphere.Auth.OidcProvider.Services;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace DysonNetwork.Sphere.Pages.Auth;
|
||||
|
||||
[Authorize]
|
||||
public class AuthorizeModel(OidcProviderService oidcService) : PageModel
|
||||
{
|
||||
[BindProperty(SupportsGet = true)]
|
||||
public string? ReturnUrl { get; set; }
|
||||
|
||||
[BindProperty(SupportsGet = true, Name = "client_id")]
|
||||
[Required(ErrorMessage = "The client_id parameter is required")]
|
||||
public string? ClientIdString { get; set; }
|
||||
|
||||
public Guid ClientId { get; set; }
|
||||
|
||||
[BindProperty(SupportsGet = true, Name = "response_type")]
|
||||
public string ResponseType { get; set; } = "code";
|
||||
|
||||
[BindProperty(SupportsGet = true, Name = "redirect_uri")]
|
||||
public string? RedirectUri { get; set; }
|
||||
|
||||
[BindProperty(SupportsGet = true)]
|
||||
public string? Scope { get; set; }
|
||||
|
||||
[BindProperty(SupportsGet = true)]
|
||||
public string? State { get; set; }
|
||||
|
||||
[BindProperty(SupportsGet = true)]
|
||||
public string? Nonce { get; set; }
|
||||
|
||||
|
||||
[BindProperty(SupportsGet = true, Name = "code_challenge")]
|
||||
public string? CodeChallenge { get; set; }
|
||||
|
||||
[BindProperty(SupportsGet = true, Name = "code_challenge_method")]
|
||||
public string? CodeChallengeMethod { get; set; }
|
||||
|
||||
[BindProperty(SupportsGet = true, Name = "response_mode")]
|
||||
public string? ResponseMode { get; set; }
|
||||
|
||||
public string? AppName { get; set; }
|
||||
public string? AppLogo { get; set; }
|
||||
public string? AppUri { get; set; }
|
||||
public string[]? RequestedScopes { get; set; }
|
||||
|
||||
public async Task<IActionResult> OnGetAsync()
|
||||
{
|
||||
if (string.IsNullOrEmpty(ClientIdString) || !Guid.TryParse(ClientIdString, out var clientId))
|
||||
{
|
||||
ModelState.AddModelError("client_id", "Invalid client_id format");
|
||||
return BadRequest("Invalid client_id format");
|
||||
}
|
||||
|
||||
ClientId = clientId;
|
||||
|
||||
var client = await oidcService.FindClientByIdAsync(ClientId);
|
||||
if (client == null)
|
||||
{
|
||||
ModelState.AddModelError("client_id", "Client not found");
|
||||
return NotFound("Client not found");
|
||||
}
|
||||
|
||||
AppName = client.Name;
|
||||
AppLogo = client.LogoUri;
|
||||
AppUri = client.ClientUri;
|
||||
RequestedScopes = (Scope ?? "openid profile").Split(' ').Distinct().ToArray();
|
||||
|
||||
return Page();
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostAsync(bool allow)
|
||||
{
|
||||
// First validate the client ID
|
||||
if (string.IsNullOrEmpty(ClientIdString) || !Guid.TryParse(ClientIdString, out var clientId))
|
||||
{
|
||||
ModelState.AddModelError("client_id", "Invalid client_id format");
|
||||
return BadRequest("Invalid client_id format");
|
||||
}
|
||||
|
||||
ClientId = clientId;
|
||||
|
||||
// Check if client exists
|
||||
var client = await oidcService.FindClientByIdAsync(ClientId);
|
||||
if (client == null)
|
||||
{
|
||||
ModelState.AddModelError("client_id", "Client not found");
|
||||
return NotFound("Client not found");
|
||||
}
|
||||
|
||||
if (!allow)
|
||||
{
|
||||
// User denied the authorization request
|
||||
if (string.IsNullOrEmpty(RedirectUri))
|
||||
return BadRequest("No redirect_uri provided");
|
||||
|
||||
var deniedUriBuilder = new UriBuilder(RedirectUri);
|
||||
var deniedQuery = System.Web.HttpUtility.ParseQueryString(deniedUriBuilder.Query);
|
||||
deniedQuery["error"] = "access_denied";
|
||||
deniedQuery["error_description"] = "The user denied the authorization request";
|
||||
if (!string.IsNullOrEmpty(State)) deniedQuery["state"] = State;
|
||||
deniedUriBuilder.Query = deniedQuery.ToString();
|
||||
|
||||
return Redirect(deniedUriBuilder.ToString());
|
||||
}
|
||||
|
||||
// User approved the request
|
||||
if (string.IsNullOrEmpty(RedirectUri))
|
||||
{
|
||||
ModelState.AddModelError("redirect_uri", "No redirect_uri provided");
|
||||
return BadRequest("No redirect_uri provided");
|
||||
}
|
||||
|
||||
// Generate authorization code
|
||||
var authCode = await oidcService.GenerateAuthorizationCodeAsync(
|
||||
clientId: ClientId,
|
||||
userId: User.Identity?.Name ?? string.Empty,
|
||||
redirectUri: RedirectUri,
|
||||
scopes: Scope?.Split(' ', StringSplitOptions.RemoveEmptyEntries) ?? Array.Empty<string>(),
|
||||
codeChallenge: CodeChallenge,
|
||||
codeChallengeMethod: CodeChallengeMethod,
|
||||
nonce: Nonce);
|
||||
|
||||
// Build the redirect URI with the authorization code
|
||||
var redirectUri = new UriBuilder(RedirectUri);
|
||||
var query = System.Web.HttpUtility.ParseQueryString(redirectUri.Query);
|
||||
|
||||
// Add the authorization code
|
||||
query["code"] = authCode;
|
||||
|
||||
// Add state if provided (for CSRF protection)
|
||||
if (!string.IsNullOrEmpty(State))
|
||||
{
|
||||
query["state"] = State;
|
||||
}
|
||||
|
||||
// Set the query string
|
||||
redirectUri.Query = query.ToString();
|
||||
|
||||
// Redirect back to the client with the authorization code
|
||||
return Redirect(redirectUri.ToString());
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user