Instantly share code, notes, and snippets.

Embed
What would you like to do?
Buggy Attempt at porting ServiceStack's AspNetWindowsAuthProvider to .NET Core
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using Microsoft.AspNetCore.Http;
using ServiceStack;
using ServiceStack.Auth;
using ServiceStack.Web;
public class AspNetCoreWindowsAuthProvider : AuthProvider, IAuthWithRequest
{
public static string Name = AuthenticateService.WindowsAuthProvider;
public static string Realm = "/auth/" + AuthenticateService.WindowsAuthProvider;
public AspNetCoreWindowsAuthProvider(IAppHost appHost)
{
Provider = Name;
AuthRealm = Realm;
AllRoles = new List<string>();
LimitAccessToRoles = new List<string>();
PopulateUserRoles = PopulateUserSessionWithIsInRole;
//Add all pre-defined Roles used to in App to 'AllRoles'
appHost.AfterInitCallbacks.Add(host =>
{
var requiredRoles = host.Metadata.OperationsMap
.SelectMany(x => x.Key.AllAttributes<RequiredRoleAttribute>()
.Concat(x.Value.ServiceType.AllAttributes<RequiredRoleAttribute>()))
.SelectMany(x => x.RequiredRoles);
requiredRoles.Each(x => AllRoles.AddIfNotExists(x));
});
}
/// <summary>
/// Specify all roles to be used by this application
/// </summary>
public List<string> AllRoles { get; set; }
/// <summary>
/// Only allow access to users in specified roles
/// </summary>
public List<string> LimitAccessToRoles { get; set; }
public Action<IRequest, IPrincipal, IAuthSession> PopulateUserRoles { get; set; }
public bool AllowAllWindowsAuthUsers
{
get => LimitAccessToRoles == null;
set => LimitAccessToRoles = null;
}
private void PopulateUserSessionWithIsInRole(IRequest req, IPrincipal user, IAuthSession session)
{
foreach (var role in AllRoles.Safe())
{
if (session.Roles.Contains(role))
continue;
if (user.IsInRole(role))
session.Roles.AddIfNotExists(role);
}
}
public override bool IsAuthorized(IAuthSession session, IAuthTokens tokens, Authenticate request = null)
{
return session != null && session.IsAuthenticated;
// && LoginMatchesSession(session, ctx.User.Identity.Name);
}
public virtual bool IsAuthorized(IPrincipal user)
{
if (user != null)
{
if (!user.Identity.IsAuthenticated)
return false;
if (AllowAllWindowsAuthUsers)
return true;
if (LimitAccessToRoles.Any(user.IsInRole))
return true;
}
return false;
}
public override object Authenticate(IServiceBase authService, IAuthSession session, Authenticate request)
{
var user = (authService.Request.OriginalRequest as HttpRequest).HttpContext.User;
var userName = user.Identity.Name;
if (!LoginMatchesSession(session, userName))
{
authService.RemoveSession();
session = authService.GetSession();
}
if (IsAuthorized(user))
{
session.IsAuthenticated = true;
if (session.UserAuthName == null)
{
session.UserAuthName = userName;
}
var netCoreReq = authService.Request.OriginalRequest as HttpRequest;
session.DisplayName = netCoreReq.HttpContext.User.Identity.Name;
var tokens = new AuthTokens
{
Provider = Name,
UserName = userName,
DisplayName = session.DisplayName,
Items = new Dictionary<string, string>
{
{"LogonUserIdentityName", session.DisplayName}
}
};
session.ReferrerUrl = GetReferrerUrl(authService, session, request);
var response = OnAuthenticated(authService, session, tokens, new Dictionary<string, string>());
if (session.Roles == null)
session.Roles = new List<string>();
PopulateUserRoles(authService.Request, user, session);
this.SaveSession(authService, session, SessionExpiry);
if (response != null)
return response;
return new AuthenticateResponse
{
UserName = userName,
SessionId = session.Id,
DisplayName = session.DisplayName,
ReferrerUrl = request.Continue
};
}
throw HttpError.Unauthorized(ErrorMessages.WindowsAuthFailed.Localize(authService.Request));
}
protected override IAuthRepository GetAuthRepository(IRequest req)
{
return null; //Sources User Info from Windows Auth instead of Auth Repo
}
public static void AuthenticateIfWindowsAuth(IRequest req, IResponse res)
{
var winAuthProvider = AuthenticateService.GetAuthProvider(Name) as AspNetCoreWindowsAuthProvider;
winAuthProvider?.IsAuthorized(((HttpRequest)req.OriginalRequest).HttpContext.User);
}
public void PreAuthenticate(IRequest req, IResponse res)
{
var netcoreReq = req.OriginalRequest as HttpRequest;
var user = netcoreReq?.HttpContext.User;
if (user != null)
{
SessionFeature.AddSessionIdToRequestFilter(req, res, null);
using (var authService = HostContext.ResolveService<AuthenticateService>(req))
{
var session = req.GetSession();
if (LoginMatchesSession(session, user.Identity.Name)) return;
var response = authService.Post(new Authenticate
{
provider = Name,
UserName = user.Identity.Name
});
}
}
}
}
@daleholborow

This comment has been minimized.

Show comment
Hide comment
@daleholborow

daleholborow Aug 28, 2018

You mention that this is buggy - I'll try it out today, but what bugs in particular did you encounter?

daleholborow commented Aug 28, 2018

You mention that this is buggy - I'll try it out today, but what bugs in particular did you encounter?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment