Solved

OWIN OpenID MVC5 - Dynamically Change the OpenID Service Provider URL...

Posted on 2015-02-24
13
124 Views
Last Modified: 2015-03-25
Tools: VS2013, C#, MVC5

I have defined an OpenID provider in Startup.Auth.cs.

When you click on the OpenID button on the login page, you are directed to the ExternalLogin action in the AccountController. So far, so good.

My question is this:

How\when can I dynamically change the URL for the OpenID service provider that was set in Startup.Auth.cs?

Thanks in advance,

Rick
0
Comment
Question by:sadlermd
  • 7
  • 6
13 Comments
 
LVL 96

Expert Comment

by:Bob Learned
ID: 40630714
Can you show me the code in Startup.Auth.cs for the provider please?
0
 

Author Comment

by:sadlermd
ID: 40630999
I am using this library:

https://github.com/owin-middleware/OwinOAuthProviders

one of the (many) sample implementations is this:

app.UseOpenIDAuthentication("https://www.google.com/accounts/o8/id", "Google");
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 40631382
If you are asking for a way to change the URL for OpenID authentication, it seems like it is right in front of me:

app.UseOpenIDAuthentication("https://www.google.com/accounts/o8/id", "Google");
0
Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

 

Author Comment

by:sadlermd
ID: 40631582
That is set during Startup;

What i need to do is change that URL after they click login and are redirected to the ExternalLogin() action.

I would like to change that provider URL dynamically in ExternalLogin().

Part of the problem is having a valid instance of IAppBuilder.app in the controller.
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 40631811
Now that I understand your question, I would think that you could solve this problem by keeping an instance of the OAuth provider, but I am not sure if there is a property for the URL.
0
 

Author Comment

by:sadlermd
ID: 40631939
This command returns the list of providers:

"HttpContext.GetOwinContext().Authentication.GetExternalAuthenticationTypes()"

However, it only provides the Caption (i.e. "Google") and the AuthenticationType ("ExternalCookie").

If u have a code example of how u might proceed with keeping an instance of the provider around, that would be a big help!

thanks
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 40633286
I downloaded the provider source code, and when I use that code, I get this exception:

'Microsoft.Owin.Security.IAuthenticationManager' does not contain a definition for 'GetExternalAuthenticationTypes' and no extension method 'GetExternalAuthenticationTypes' accepting a first argument of type 'Microsoft.Owin.Security.IAuthenticationManager' could be found (are you missing a using directive or an assembly reference?


The version for Microsoft.Owin.Security is 2.1.0.0.
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 40633304
I did find GetAuthenticationTypes, which returns IEnumerable<AuthenticationDescription>.  That only provides a description, not an instance.  I am still looking for the magic for getting the instance of the provider.
0
 

Author Comment

by:sadlermd
ID: 40633350
I'm glad I'm not the only one who feels like magic is required!

Looking forward to hearing your findings...
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 40633458
I was able to get the OpenIDAuthenticationOptions instance, which has the discovery URI for Google.  When the AppBuilder.Use is called, it stores some information about the middleware element in the _middleware field:

  public IAppBuilder Use(object middleware, params object[] args)
        {
            this._middleware.Add(AppBuilder.ToMiddlewareFactory(middleware, args));
            return this;
        }

Open in new window


This reflection code, sets up Google OAuth, which stores the URI in the OpenIDAuthenticationOptions, and then pulls the options back from the _middleware field.  I haven't found a property to access the options.  

Another possibility, though, might be to create your own class, which inherits from OpenIDAuthenticationMiddleware, and then extend the class to give you the functionality that you need.

  app.UseOpenIDAuthentication("https://www.google.com/accounts/o8/id", "Google");

            var field = app.GetType().GetField("_middleware", BindingFlags.NonPublic | BindingFlags.Instance);

            var middlewareList = (IList<Tuple<Type, Delegate, object[]>>)field.GetValue(app);

            var optionList = middlewareList
                .SelectMany(x => x.Item3)
                .ToList();

            var openIdOptions = optionList
                .OfType<OpenIDAuthenticationOptions>()
                .FirstOrDefault();

            if (openIdOptions != null)
            {
                var uri = openIdOptions.ProviderDiscoveryUri;
                Console.WriteLine(uri);
            }

Open in new window

0
 

Accepted Solution

by:
sadlermd earned 0 total points
ID: 40635969
I will review your suggestion this weekend - for now, I have chosen to do the following:

1. Create list (dynamically) of the service providers I need to support.
2. Add code to Startup.Auth that gets the names in that list and calls app.UseOpenIDAuthentication(var1, var2)

This allows me to achieve my end goal of insuring that I am not using hard-coded providers values...
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 40636129
Using multiple OpenIDAuthenticationMiddleware instances is probably the better approach, but I want to explore the other possibility of getting an instance of the class, too.
0
 

Author Closing Comment

by:sadlermd
ID: 40686688
This approach provided a simple but dynamic solution to the problem.

1. Create table that contains details required when calling UseOpenIDAuthentication().
2. Add method that retrieved table content.
3. Iterate over list and call UseOpenIDAuthentication(key, value);

Bob's answer could possibly work, however I didn't get a chance to test it.
0

Featured Post

3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
JQuery JavaScripot loop though RadioButtonList 4 25
Batch file or script with password 22 44
Help with converting xml file to excel using VB.NET 3 20
QQ problem 22 23
What is Node.js? Node.js is a server side scripting language much like PHP or ASP but is used to implement the complete package of HTTP webserver and application framework. The difference is that Node.js’s execution engine is asynchronous and event…
The article shows the basic steps of integrating an HTML theme template into an ASP.NET MVC project
Use Wufoo, an online form creation tool, to make powerful forms. Learn how to selectively show certain fields based on user input using rules to gather relevant information and data from your forms. The rules feature provides you with an opportunity…
Learn how to set-up custom confirmation messages to users who complete your Wufoo form. Include inputs from fields in your form, webpage redirects, and more with Wufoo’s confirmation options.

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question