Skip to content

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.

Copy link

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
You can’t perform that action at this time.