简体   繁体   中英

Processing AuthenticationResult's from different providers in the same page

I'm integrating OpenID to my existing application with LiveID and Google providers. On my login page, in addition to the original login fields I have added 'Log in with Google' and 'Log in with Microsoft' buttons.

I can successfully read the AuthenticationResult data for both providers above, but am accomplishing this in the following manner...

For the new login buttons I crafted a return URL to differentiate them on the user's return:

Protected Sub btn_google_Click(sender As Object, e As EventArgs) Handles btn_google.Click
    Dim client As New GoogleOpenIdClient
    Dim u As New System.Uri("http://www.mytest.com/login.aspx?action=signin&provider=google")
    client.RequestAuthentication(New HttpContextWrapper(HttpContext.Current), u)
End Sub

Protected Sub btn_live_Click(sender As Object, e As EventArgs) Handles btn_live.Click
    Dim client As New MicrosoftClient("xyz", "12345")
    Dim u As New System.Uri("http://www.mytest.com/login.aspx?action=signin&provider=microsoft")
    client.RequestAuthentication(New HttpContextWrapper(HttpContext.Current), u)
End Sub

So when the user gets redirected back to login.aspx, I then have the following checks to process the login functionality:

If Not Page.IsPostBack Then
    If Request.QueryString("action") IsNot Nothing AndAlso Request.QueryString("action").Trim = "signin" Then
        If Request.QueryString("provider") IsNot Nothing AndAlso Request.QueryString("provider").Trim <> String.Empty Then
            Select Case Request.QueryString("provider").Trim
                Case "microsoft"
                    Dim client As New MicrosoftClient("xyz", "12345")
                    Dim u As New System.Uri("http://www.mytest.com/loginlive.aspx?action=signin&provider=microsoft")
                    Dim result As DotNetOpenAuth.AspNet.AuthenticationResult = client.VerifyAuthentication(New HttpContextWrapper(HttpContext.Current), u)
                    ' remainder of logic removed
                    ' ...
                Case "google"
                    Dim client As New GoogleOpenIdClient
                    Dim result As DotNetOpenAuth.AspNet.AuthenticationResult = client.VerifyAuthentication(New HttpContextWrapper(HttpContext.Current))
                    ' remainder of logic removed
                    ' ...
            End Select
        End
    End
End If

My main question here is, is this a good way to process AuthenticationResults? Or, is there a better/more secure/more clever way to accomplish the same?

Better way would be to use Abstract Factory pattern in combination with Command Pattern. Which can reduce the hard coding and also have the code loosely coupled, so you can extend the functionality in future for each of the authentication provider. Find the snippet of each section of the code below

Abstract Class for "BaseAuthentication Provider"

public abstract class BaseAuthenticationProvider
{
    //abstract Methods that need to be invoked from the concrete class, this need to be decided based on the functionality you need to achieve. This function would be invoked using the command pattern.
    // AuthorizeUser() : this method would be invoked to authorize the user from the provider

   //AuthenticateUser() : this method would be invoked once the user is redirected from the provider site.

    //abstract Properties that will hold the base information for the authentication provider, this need to be decided based on the functionality you need to achieve
    //CustomerSecret
    //CustomerConsumerKey
}

Use the following code snippet to implement concrete class for the Gooogle, Yahoo, Microsoft etc.

public class GoogleAuthentication : BaseAuthenticationProvider
{
     public GoogleAuthentication()
     {
          //initialization
     }

     public void AuthorizeUser()
     {
          //code
     }

     public string CustomerSecret()
     {
          //code
     }

     public string CustomerConsumerKey()
     {
          //code
     }
}

Factory class to create the concrete object , to prevent from creating instance of this factory class implement a private constructor.

public class AuthenticationProviderFactory
{
     private AuthenticationProviderFactory()
     {
     }

     public static BaseAuthenticationProvider GetInstance(string Domain)
     {
          switch (Domain)
          {
               case "google":
                    return new GoogleAuthentication();
               case "yahoo":
                    return new YahooAuthentication();
           }
      }
 }

Login.aspx : have buttons for each of the authentication provider, set the value for "CommandName" for each of the button and link all the buttons to the same event handler

for eg btn_google.CommandName = "google"

Protected Sub AuthenticationProvider_Click(sender As Object, e As EventArgs) Handles btn_google.Click, btn_yahoo.Click
    AuthenticationProviderFactory.GetInstance(((Button)sender).CommandName).AuthorizeUser();
End Sub

Respective AuthorizeUser method would call the respective provider site for authentication. When provider redirects the user to the return URL, apply the same pattern on the Page_Load event and call the Autheticate Method from the abstract class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM