Solved

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

Posted on 2015-02-24
13
134 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
MIM Survival Guide for Service Desk Managers

Major incidents can send mastered service desk processes into disorder. Systems and tools produce the data needed to resolve these incidents, but your challenge is getting that information to the right people fast. Check out the Survival Guide and begin bringing order to chaos.

 

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

MIM Survival Guide for Service Desk Managers

Major incidents can send mastered service desk processes into disorder. Systems and tools produce the data needed to resolve these incidents, but your challenge is getting that information to the right people fast. Check out the Survival Guide and begin bringing order to chaos.

Question has a verified solution.

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

If I have to fix slow responding website my first thoughts are server side optimizations: the database may not be optimized or caching is not enabled, or things like that. We often overlook another major part of our web application: the client. We o…
Entity Framework is a powerful tool to help you interact with the DataBase but still doesn't help much when we have a Stored Procedure that returns more than one resultset. The solution takes some of out-of-the-box thinking; read on!
This video teaches viewers how to create their own website using cPanel and Wordpress. Tutorial walks users through how to set up their own domain name from tools like Domain Registrar, Hosting Account, and Wordpress. More specifically, the order in…
Learn how to set-up PayPal payment integration in your Wufoo form. Allow your users to remit payment through PayPal upon completion of your online form. This is helpful for collecting membership payments, customer payments, donations, and more.

733 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