Solved

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

Posted on 2015-02-24
13
149 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
Get 15 Days FREE Full-Featured Trial

Benefit from a mission critical IT monitoring with Monitis Premium or get it FREE for your entry level monitoring needs.
-Over 200,000 users
-More than 300,000 websites monitored
-Used in 197 countries
-Recommended by 98% of users

 

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

[Webinar] Learn How Hackers Steal Your Credentials

Do You Know How Hackers Steal Your Credentials? Join us and Skyport Systems to learn how hackers steal your credentials and why Active Directory must be secure to stop them. Thursday, July 13, 2017 10:00 A.M. PDT

Question has a verified solution.

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

A long time ago (May 2011), I have written an article showing you how to create a DLL using Visual Studio 2005 to be hosted in SQL Server 2005. That was valid at that time and it is still valid if you are still using these versions. You can still re…
It was really hard time for me to get the understanding of Delegates in C#. I went through many websites and articles but I found them very clumsy. After going through those sites, I noted down the points in a easy way so here I am sharing that unde…
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…
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…

696 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