I am trying to take over the Orchard admin authentication flow and replace it with OpenId Connect using Azure AD instead (for SSO purposes). After the user is authenticated with OpenId I want to then sign the user in to Orchard to use Orchard's roles for authorization.
This is the code I have so far
OwinMiddlewareProvider:
public class OpenIdConnectMiddleware : IOwinMiddlewareProvider
{
public IEnumerable<OwinMiddlewareRegistration> GetOwinMiddlewares()
{
return new[]
{
new OwinMiddlewareRegistration
{
Priority = "1",
Configure = app => {
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = "<My Client Id>",
Authority = "<My Authority>",
RedirectUri = "https://localhost:44357/"
});
}
}
};
}
}
My route for taking over the default access denied route:
new RouteDescriptor {
Priority = 1,
Route = new Route(
"Users/Account/AccessDenied",
new RouteValueDictionary {
{"area", "BCS.Authentication"},
{"controller", "Account"},
{"action", "LogOn"}
},
new RouteValueDictionary (),
new RouteValueDictionary {
{"area", "BCS.Authentication"}
},
new MvcRouteHandler())
}
And finally, my AccountController has the following:
public ActionResult LogOn(string returnUrl)
{
if (!Request.IsAuthenticated)
{
HttpContext.GetOwinContext().Authentication.Challenge(
new AuthenticationProperties { RedirectUri = string.IsNullOrEmpty(returnUrl) ? "/" : returnUrl },
OpenIdConnectAuthenticationDefaults.AuthenticationType);
return new EmptyResult();
}
var currentUser = _authenticationService.GetAuthenticatedUser();
if (currentUser == null)
{
// temporary, just for testing purposes
var user = _membershipService.GetUser("douwinga");
_authenticationService.SignIn(user, false);
}
return new RedirectResult(returnUrl);
}
With this code when I navigate to https://localhost:44357/admin Request.IsAuthenticated is false so it takes me to our ADFS login page. After I sign in I am taken back to the LogOn action and Request.IsAuthenticated is now true. It then tries to use the authenticationService to see if I am authenticated with Orchard and obviously returns null, so it then signs me in to Orchard. If I check the authenticationService to see if I am logged in after the sign in, it returns my user, so I am authenticated with Orchard at this point.
Then comes the issue. I am redirected to /admin now that I am authenticated and it does another authentication check, so I am sent back to the LogOn action of my controller. This time Request.IsAuthenticated is still true, but currentUser is still null, so I am no longer authenticated with Orchard, so it tries to login to Orchard again. This then puts me in a loop.
Is there something I am missing? Is there a better approach?
There is a new module that Radio Systems has been working on. It's also used internally at Microsoft and will be included in Orchard ASAP
https://github.com/RadioSystems/RadioSystems.AzureAuthentication