Skip to content

Instantly share code, notes, and snippets.

@joeriks
Last active February 6, 2017 08:10
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joeriks/4518393 to your computer and use it in GitHub Desktop.
Save joeriks/4518393 to your computer and use it in GitHub Desktop.
[CustomAuthenticate] attribute for ServiceStack, the same as the regular Authenticate, except the regular does not work with Custom credentials (fixed with line 117), plus experimental (works on my machine) authorization with session id in header (for ajax cors requests that require custom authentidcation), see line 95ff: 1. Authorize the regula…
using System;
using System.Linq;
using ServiceStack.Common;
using ServiceStack.Common.Web;
using ServiceStack.ServiceHost;
using ServiceStack.ServiceInterface.Auth;
using ServiceStack.Text;
using ServiceStack.WebHost.Endpoints.Extensions;
namespace ServiceStack.ServiceInterface
{
/// <summary>
/// Same as AuthenticateAttribute but adds option to keep session
/// with cors ajax with sessionid in Authorization header
/// 1. Authorize the regular way, keep the session id (in cookie or just in js)
/// 2. Send the session id in each request: xhr.setRequestHeader("Session-Id", = "{sessionid}");
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public class CustomAuthenticateAttribute : RequestFilterAttribute
{
public string Provider { get; set; }
public string HtmlRedirect { get; set; }
public CustomAuthenticateAttribute(ApplyTo applyTo)
: base(applyTo)
{
this.Priority = (int)RequestFilterPriority.Authenticate;
}
public CustomAuthenticateAttribute()
: this(ApplyTo.All) { }
public CustomAuthenticateAttribute(string provider)
: this(ApplyTo.All)
{
this.Provider = provider;
}
public CustomAuthenticateAttribute(ApplyTo applyTo, string provider)
: this(applyTo)
{
this.Provider = provider;
}
public override void Execute(IHttpRequest req, IHttpResponse res, object requestDto)
{
if (AuthService.AuthProviders == null) throw new InvalidOperationException("The AuthService must be initialized by calling "
+ "AuthService.Init to use an authenticate attribute");
var matchingOAuthConfigs = AuthService.AuthProviders.Where(x =>
this.Provider.IsNullOrEmpty()
|| x.Provider == this.Provider).ToList();
if (matchingOAuthConfigs.Count == 0)
{
res.WriteError(req, requestDto, "No OAuth Configs found matching {0} provider"
.Fmt(this.Provider ?? "any"));
res.EndServiceStackRequest();
return;
}
AuthenticateIfDigestAuth(req, res);
AuthenticateIfBasicAuth(req, res);
SetSessionIfSessionIdHeader(req, res);
using (var cache = req.GetCacheClient())
{
var sessionId = req.GetSessionId();
var session = sessionId != null ? cache.GetSession(sessionId) : null;
if (session == null || !matchingOAuthConfigs.Any(x => session.IsAuthorized(x.Provider)))
{
var htmlRedirect = HtmlRedirect ?? AuthService.HtmlRedirect;
if (htmlRedirect != null && req.ResponseContentType.MatchesContentType(ContentType.Html))
{
var url = htmlRedirect;
if (url.SafeSubstring(0, 2) == "~/")
{
url = req.GetBaseUrl().CombineWith(url.Substring(2));
}
url = url.AddQueryParam("redirect", req.AbsoluteUri);
res.RedirectToUrl(url);
return;
}
AuthProvider.HandleFailedAuth(matchingOAuthConfigs[0], session, req, res);
}
}
}
private string sessionIdFromHeader(IHttpRequest httpReq)
{
var sessionId = httpReq.Headers["Session-Id"];
return sessionId;
}
private void SetSessionIfSessionIdHeader(IHttpRequest req, IHttpResponse res)
{
var tokenSessionId = sessionIdFromHeader(req);
if (tokenSessionId != null)
{
req.Items[SessionFeature.SessionId] = tokenSessionId;
req.Items[SessionFeature.PermanentSessionId] = tokenSessionId;
}
}
public static void AuthenticateIfBasicAuth(IHttpRequest req, IHttpResponse res)
{
//Need to run SessionFeature filter since its not executed before this attribute (Priority -100)
SessionFeature.AddSessionIdToRequestFilter(req, res, null); //Required to get req.GetSessionId()
var userPass = req.GetBasicAuthUserAndPassword();
if (userPass != null)
{
var authService = req.TryResolve<AuthService>();
authService.RequestContext = new HttpRequestContext(req, res, null);
var response = authService.Post(new Auth.Auth
{
provider = "credentials", // changed from AuthenticateAttribute, was "basic"
UserName = userPass.Value.Key,
Password = userPass.Value.Value
});
}
}
public static void AuthenticateIfDigestAuth(IHttpRequest req, IHttpResponse res)
{
AuthenticateAttribute.AuthenticateIfDigestAuth(req, res);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment