Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I am migrating my Azure AD secured application to the v2.0 endpoint.

I need to pass a custom parameter to the reply uri. With former Azure AD endpoint I did it by adding a usual query parameter to the reply url. e.g. https://myserver.com/myredirect_uri?mycustomparamerter=myvalue

Unfortunately, with endpoint 2.0 I received an error saying that the reply uri does not match the one registered. Of course my custom parameter value is dynamic and I cannot hardcode it.

I was looking to exploit the 'state' parameter described in OAUTH flow. However, I am using Microsoft.Owin.Security.OpenIdConnect and it looks the parameter is already set so I cannot exploit it. I am using an implementation of the flow that is based on MVC that looks like this sample.

Can you suggest a workaround so my server receive a custom parameter in the reply url that have been set on the flow start?

like image 729
Benoit Patra Avatar asked May 27 '16 18:05

Benoit Patra


1 Answers

Not sure if there's an official way to do what you're asking but one way you could technically inject and extract extra values through the auth flow is via OWIN's notifications.

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 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 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 barring a better overall approach.

like image 189
Saca Avatar answered Nov 03 '22 01:11

Saca