forked from loic-sharma/BaGet
-
Notifications
You must be signed in to change notification settings - Fork 57
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Implement private feeds (#156)
* Private feed implementation * case insensitive username * Cleanup * Cleanup * Implement multi auth resolves #147 * Prevent null exception. * Requested changes * fix comment * Documentation * Update config docs * Update apikeys docs * feedback impl * Tests * Integration tests for basic authentication * CodeMaid * Remove redundant call * Move auth handler and tests * ApiKey to object * Move auth config to extend BaGetterApplication * Api keys move into auth * docs * formatting * VS Package manager console guide * remove extra space * Unify line style * Allow auth policies config * Using * Move auth config to Bagetter project * Remove sealed class * Auth options comments * Fix tests * Fix build --------- Co-authored-by: seriouz <seriouz@users.noreply.github.com>
- Loading branch information
Showing
23 changed files
with
656 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
12 changes: 12 additions & 0 deletions
12
src/BaGetter.Core/Authentication/AuthenticationConstants.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace BaGetter.Authentication; | ||
public static class AuthenticationConstants | ||
{ | ||
public const string NugetBasicAuthenticationScheme = "NugetBasicAuthentication"; | ||
public const string NugetUserPolicy = "NuGetUserPolicy"; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace BaGetter.Core.Configuration; | ||
public class ApiKey | ||
{ | ||
public string Key { get; set; } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 16 additions & 0 deletions
16
src/BaGetter.Core/Configuration/NugetAuthenticationOptions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
using BaGetter.Core.Configuration; | ||
|
||
namespace BaGetter.Core; | ||
|
||
public sealed class NugetAuthenticationOptions | ||
{ | ||
/// <summary> | ||
/// Username and password credentials for downloading packages. | ||
/// </summary> | ||
public NugetCredentials[] Credentials { get; set; } | ||
|
||
/// <summary> | ||
/// Api keys for pushing packages into the feed. | ||
/// </summary> | ||
public ApiKey[] ApiKeys { get; set; } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
namespace BaGetter.Core; | ||
|
||
public sealed class NugetCredentials | ||
{ | ||
public string Username { get; set; } | ||
|
||
public string Password { get; set; } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
100 changes: 100 additions & 0 deletions
100
src/BaGetter.Web/Authentication/NugetBasicAuthenticationHandler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
using Microsoft.AspNetCore.Authentication; | ||
using Microsoft.Extensions.Logging; | ||
using Microsoft.Extensions.Options; | ||
using System.Net.Http.Headers; | ||
using System.Security.Claims; | ||
using System.Text.Encodings.Web; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using System; | ||
using BaGetter.Core; | ||
using System.Linq; | ||
|
||
namespace BaGetter.Web.Authentication; | ||
|
||
public class NugetBasicAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions> | ||
{ | ||
private readonly IOptions<BaGetterOptions> bagetterOptions; | ||
|
||
public NugetBasicAuthenticationHandler( | ||
IOptionsMonitor<AuthenticationSchemeOptions> options, | ||
ILoggerFactory logger, | ||
UrlEncoder encoder, | ||
IOptions<BaGetterOptions> bagetterOptions) | ||
: base(options, logger, encoder) | ||
{ | ||
this.bagetterOptions = bagetterOptions; | ||
} | ||
|
||
protected override Task<AuthenticateResult> HandleAuthenticateAsync() | ||
{ | ||
if (IsAnonymousAllowed()) | ||
{ | ||
return CreateAnonymousAuthenticatonResult(); | ||
} | ||
|
||
if (!Request.Headers.TryGetValue("Authorization", out var auth)) | ||
return Task.FromResult(AuthenticateResult.NoResult()); | ||
|
||
string username = null; | ||
string password = null; | ||
try | ||
{ | ||
var authHeader = AuthenticationHeaderValue.Parse(auth); | ||
var credentialBytes = Convert.FromBase64String(authHeader.Parameter); | ||
var credentials = Encoding.UTF8.GetString(credentialBytes).Split([':'], 2); | ||
username = credentials[0]; | ||
password = credentials[1]; | ||
} | ||
catch | ||
{ | ||
return Task.FromResult(AuthenticateResult.Fail("Invalid Authorization Header")); | ||
} | ||
|
||
if (!ValidateCredentials(username, password)) | ||
return Task.FromResult(AuthenticateResult.Fail("Invalid Username or Password")); | ||
|
||
return CreateUserAuthenticatonResult(username); | ||
} | ||
|
||
protected override async Task HandleChallengeAsync(AuthenticationProperties properties) | ||
{ | ||
Response.Headers.WWWAuthenticate = "Basic realm=\"NuGet Server\""; | ||
await base.HandleChallengeAsync(properties); | ||
} | ||
|
||
private Task<AuthenticateResult> CreateAnonymousAuthenticatonResult() | ||
{ | ||
Claim[] claims = [new Claim(ClaimTypes.Anonymous, string.Empty)]; | ||
var identity = new ClaimsIdentity(claims, Scheme.Name); | ||
var principal = new ClaimsPrincipal(identity); | ||
|
||
var ticket = new AuthenticationTicket(principal, Scheme.Name); | ||
|
||
return Task.FromResult(AuthenticateResult.Success(ticket)); | ||
} | ||
|
||
private Task<AuthenticateResult> CreateUserAuthenticatonResult(string username) | ||
{ | ||
Claim[] claims = [new Claim(ClaimTypes.Name, username)]; | ||
var identity = new ClaimsIdentity(claims, Scheme.Name); | ||
var principal = new ClaimsPrincipal(identity); | ||
|
||
var ticket = new AuthenticationTicket(principal, Scheme.Name); | ||
|
||
return Task.FromResult(AuthenticateResult.Success(ticket)); | ||
} | ||
|
||
private bool IsAnonymousAllowed() | ||
{ | ||
return bagetterOptions.Value.Authentication is null || | ||
bagetterOptions.Value.Authentication.Credentials is null || | ||
bagetterOptions.Value.Authentication.Credentials.Length == 0 || | ||
bagetterOptions.Value.Authentication.Credentials.All(a => string.IsNullOrWhiteSpace(a.Username) && string.IsNullOrWhiteSpace(a.Password)); | ||
} | ||
|
||
private bool ValidateCredentials(string username, string password) | ||
{ | ||
return bagetterOptions.Value.Authentication.Credentials.Any(a => a.Username.Equals(username, StringComparison.OrdinalIgnoreCase) && a.Password == password); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.