Passing parameters to Azure Active Directory authentication

Similar to what Gaurav is suggesting, but adding a few special considerations. Basically, the state is used by the Owin middleware, so while you can inject your own stuff, you need to make sure you revert it back before the Owin middleware tries to use it otherwise you'll get auth errors.

This is effectively what I replied to a very similar question:

Custom parameter with Microsoft.Owin.Security.OpenIdConnect and AzureAD v 2.0 endpoint

In Startup.Auth.cs, when you setup the OpenIdConnectAuthenticationOptions you'd add the following:

app.UseOpenIdConnectAuthentication(
  new OpenIdConnectAuthenticationOptions
  {
    //...
    Notifications = new OpenIdConnectAuthenticationNotifications
    {
      RedirectToIdentityProvider = OnRedirectToIdentityProvider,
      MessageReceived = OnMessageReceived
    },
  });

And use RedirectToIdentityProvider to inject your parameter, something along the lines of:

private static Task OnRedirectToIdentityProvider(RedirectToIdentityProviderNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
  var stateQueryString = notification.ProtocolMessage.State.Split('=');
  var protectedState = stateQueryString[1];
  var state = notification.Options.StateDataFormat.Unprotect(protectedState);
  state.Dictionary.Add("mycustomparameter", "myvalue");
  notification.ProtocolMessage.State = stateQueryString[0] + "=" + notification.Options.StateDataFormat.Protect(state);
  return Task.FromResult(0);
}

And then use MessageReceived to extract it, like so:

private static Task OnMessageReceived(MessageReceivedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
  string mycustomparameter;
  var protectedState = notification.ProtocolMessage.State.Split('=')[1];
  var state = notification.Options.StateDataFormat.Unprotect(protectedState);
  state.Dictionary.TryGetValue("mycustomparameter", out mycustomparameter);
  return Task.FromResult(0);
}

You'd obviously need to improve/harden this but this should get you going.


You could pass the ProjectId parameter as value for State parameter. See the sample code below:

            Notifications = new OpenIdConnectAuthenticationNotifications()
            {
                RedirectToIdentityProvider = context =>
                    {
                        redirectUri = string.Format("{0}/", System.Web.HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority));
                        postLogoutRedirectUri = redirectUri + "sign-out";
                        context.ProtocolMessage.RedirectUri = redirectUri;
                        context.ProtocolMessage.PostLogoutRedirectUri = postLogoutRedirectUri;
                        context.ProtocolMessage.State = "Your Project Id";
                        return Task.FromResult(0);
                    },
                AuthorizationCodeReceived = context =>
                    {
                        var projectId = context.ProtocolMessage.State;//Retrieve the state in AuthorizationCodeReceived event.
                        return Task.FromResult(0);
                    }
            }
        };

UPDATE

Essentially State accepts a string parameter. In our project we needed to provide many values in the state. What we did there is created a pipe delimited string and pass that as state. When we receive the state back, we simply convert that into an array and use appropriate elements. Something like:

var state = "param1|param2|...|paramx";

Other thing you could do is create a state object (a simple class with some properties), serialize it as JSON, convert that in base64 string and pass that encoded string as state after properly url encoding it. When you receive back the state, you could do the reverse process, get state object back and use it's properties values.