Your official information source from the .NET Web Development and Tools group at Microsoft.
Over the past couple of weeks I have come across lots of questions/discussions on while OAuth/OpenId is cool as a feature in the ASP.NET templates in Visual Studio 2012, but how do I easily integrate this into my application outside of the templates. More so how do I extend the Universal Providers to integrate OAuth/OpenId and use other functionality such as roles etc. I am going to cover these two areas in this post using WebForms but you could integrate the same with MVC applications as well
Update
While the post is titled to show how you can integrate this with UniversalProviders, you can totally integrate this with SqlMembership or with your custom membership providers since Microsoft.AspNet.Membership.OpenAuth uses Membership APIs for creating users and login
I posted the following webforms project template which uses sqlmembership
https://github.com/rustd/AspNetSocialLoginSqlMembership
<authentication mode="Forms">
<forms loginUrl="Default.aspx"></forms>
</authentication>
// See http://go.microsoft.com/fwlink/?LinkId=252803 for details on setting up this ASP.NET
// application to support logging in via external services.
//OpenAuth.AuthenticationClients.AddTwitter(
// consumerKey: "your Twitter consumer key",
// consumerSecret: "your Twitter consumer secret");
//OpenAuth.AuthenticationClients.AddFacebook(
// appId: "your Facebook app id",
// appSecret: "your Facebook app secret");
//OpenAuth.AuthenticationClients.AddMicrosoft(
// clientId: "your Microsoft account client id",
// clientSecret: "your Microsoft account client secret");
OpenAuth.AuthenticationClients.AddGoogle();
<asp:ListView runat="server" ID="providerDetails" ItemType="Microsoft.AspNet.Membership.OpenAuth.ProviderDetails"
SelectMethod="GetProviderNames" ViewStateMode="Disabled">
<ItemTemplate>
<button type="submit" name="provider" value="<%#: Item.ProviderName %>"
title="Log in using your <%#: Item.ProviderDisplayName %> account.">
<%#: Item.ProviderDisplayName %>
</button>
</ItemTemplate>
<EmptyDataTemplate>
<p>There are no external authentication services configured. </p>
</EmptyDataTemplate>
</asp:ListView>
public IEnumerable<ProviderDetails> GetProviderNames()
{
return OpenAuth.AuthenticationClients.GetAll();
}
At this stage the UI will look as follows
public string ReturnUrl { get; set; }
protected void Page_Load(object sender, EventArgs e)
if (IsPostBack)
var provider = Request.Form["provider"];
if (provider == null)
return;
var redirectUrl = "~/ExternalLoginLandingPage.aspx";
if (!String.IsNullOrEmpty(ReturnUrl))
var resolvedReturnUrl = ResolveUrl(ReturnUrl);
redirectUrl += "?ReturnUrl=" + HttpUtility.UrlEncode(resolvedReturnUrl);
OpenAuth.RequestAuthentication(provider, redirectUrl);
ProcessProviderResult() in page_load does this processing
//Markup and refer to codebeind methods
<ol>
<li class="email">
<asp:Label ID="Label1" runat="server" AssociatedControlID="userName">User name</asp:Label>
<asp:TextBox runat="server" ID="userName" />
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ControlToValidate="userName"
Display="Dynamic" ErrorMessage="User name is required" ValidationGroup="NewUser" />
<asp:ModelErrorMessage ID="ModelErrorMessage2" runat="server" ModelStateKey="UserName" CssClass="field-validation-error" />
</li>
</ol>
<asp:Button ID="Button1" runat="server" Text="Log in" ValidationGroup="NewUser" OnClick="logIn_Click" />
<asp:Button ID="Button2" runat="server" Text="Cancel" CausesValidation="false" OnClick="cancel_Click" />
Once the membership user is saved to the database, the database will have the following tables
All tables would seem familiar as they are used by Universal Providers for membership, roles, profile. The 2 new tables were created by Microsoft.AspNet.Membership.OpenAuth to integrate OAuth/OpenId information with membership system.
UsersOpenAuthAccounts: This holds the information on what providers can the user login by.eg if your app is configured to use Facebook, Google then the user can login via either of them and this information will be stored here
UsersOpenAuthData: This table integrates the OAuth/Openid login to the membership system.
Following image shows how OAuth/OpenId login information is wired to membership system.
The membershipusername is the username in the Users table.At this stage since you have the users table populated you can create roles and add/remove these users from roles and thus achieve OAuth/OpenId integration with Roles as well
This entire sample is posted on my github repository(https://github.com/rustd/SocialLoginASPNET)
Feel free to download it and give it a try
To view the default templates incase you do not have VS 2012, you can browse them at the following github repro https://github.com/rustd/ASPNETTemplates
I hope this would help in integration OAuth/OpenId easily into your application when you are not starting with the templates
What if I want to be the auth service, not google or twitter etc. That's the sample I would love to see but haven't as of yet.
@Jay, can you please elaborate more on what you are looking for?
Hi, I would like to access a users Google Drive files from within my .NET application. Is this made possible once the user logs in with their Google account?
Thanks
You will have to request more parameters as indicated here developers.google.com/.../OpenID
Following post shows how you can override the built in google/facebbok etc providers and write your own to request more information blogs.msdn.com/.../extra-information-from-oauth-openid-provider.aspx
Pranav, first, THANK YOU for posting this. I have been struggling with several different approaches to FaceBook authentication and yours looks the best by far. Second, some questions. I'm using a custom membership provider and am trying to integrate your example into it.
Question 1: what are the structures of the additional SQL tables I need to create (UsersOpenAuth, etc) and where can I find some documentation on how to incorporate these tables into my custom membershipprovider?
Question 2: (related): My code gets stuck on this line in the ExternalLandingPage.aspx:
if (OpenAuth.Login(authResult.Provider, authResult.ProviderUserId, createPersistentCookie: false))
I believe it's because OpenAuth.Login is trying to execute defaultmembershipprovider methods that I do not have in my custom provider. Does that sound right? I have been unable to find a developer's reference for Microsoft.AspNet.Membership.OpenAuth -- do you have any suggestions?
Question 3: I'm writing this in ASP.NET WebForms (not MVC) 4.0. Should I be using 4.5 for any reason, or does it not matter?
Thanks again!
JB
@JB I am glad you found this post useful. You can use your CustomMembership to use this. Eventually Microsoft.AspNet.Membership.OpenAuth uses the membership APIs for login
Question1)
To see the structure of these tables, you can just run this app and inspect the schema or you can open the Microsoft.AspNet.Membership.OpenAuth.data dll in reflect. Oauth tables are EF POCO classes and have the schema defined there
Membership.OpenAuth.data should work with any custom implementation as long as you implement a membership provider. you can just use the custom membership provider in your config along with this package
Question2)
Since Membership.OpenAuth implements the membership APIs most probably your assessment is correct. Again I would recommend opening up the dll in reflector
I would also look at the CreateUser() call to see if the user is created correctly.
Question3)
This works for both v4.0 and v4.5 so it does not matter
Can I add this new membership schema into an already created database?
@Hasan, yes you can. You can pass in the connectionstring name in App_Start and the OAUth layer will use that connectionstring
Thanks for the blog post. Very useful.
Pranav you say "You can pass in the connectionstring name in App_Start and the OAUth layer will use that connectionstring" but can you provide more specific instructions on how to do this? I'm unable to find any documentation for it. Thanks!