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
Solved

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

Posted on 2015-02-24
13
126 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
How Do You Stack Up Against Your Peers?

With today’s modern enterprise so dependent on digital infrastructures, the impact of major incidents has increased dramatically. Grab the report now to gain insight into how your organization ranks against your peers and learn best-in-class strategies to resolve incidents.

 

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

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.

Question has a verified solution.

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

Foolproof security solutions has become one of the key necessities of every e-commerce or Internet banking website. If you too own an online shopping site then its vital for you to equip your web portal with customer security features that can allow…
Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
This video teaches users how to migrate an existing Wordpress website to a new domain.
Wufoo.com provides powerful tools for surveying targeted groups, and utilizing data from completed surveys to find trends, discover areas of demand or customer expectation, and make business decisions on products or services.

856 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