How to use OAuth with Forms auth
Asked Answered
N

2

8

What solutions are out there for combining a Form auth with a OAuth auth ?

Use Case:

There is an website where a user would login with a username and password and after he is auth a token will be provided, which enables access to different resources in the app for a period of time.

Now the Product Owner want's Facebook/Twitter/... Auth.

Posible solutions:

solution 1- AssServer tries to validate the Facebook ticket

edit sequence diagram

Nakashima answered 21/5, 2014 at 21:54 Comment(0)
I
13

We're actually doing this on our project. The solution was really simple. Here were the major points

  • Keep in mind that the OAuth spec recommends against storing the oauth bearer token on the client.
  • Make sure it is the app server that is making the auth requests to the oauth provider. Don't do it from the client (except on the authorization step because you don't really have a choice).
  • Leverage the framework. Let the membership provider handle authentication ticketing.
  • Create your custom membership provider and have it manage the auth process with your 3rd party provider.
  • Once auth succeeds, store the tokens in the session or within a claim with the user identity. In other words, keep the access and refresh tokens on the server.
  • Allow the framework to generate the auth ticket like it normally would
  • Between the auth ticket and the session cookie, you can retrieve the access token from the session/claim for making resource requests.
  • When associating the 3rd party login, you'll obviously have to make a call with the access token to the provider in order to get some info such as a facebook user id. Use that to link your internal user with the facebook user.

Other things to consider:

  • Make sure you destroy the session on sign out. Several frameworks will empty the cookie values but recycle the session id. Make sure the session id isn't being recycled.
  • Use an anti-forgery token with any request that requires session info which should just about everything. This will help you ensure that the session cookie wasn't hijacked.

Now, I think this is an important point: Typically, with providers like facebook and twitter, you use the authorization flow which means you have to use their form to login. They handle it, not you. There is a username/password "option" (grant_type: password) with OAuth 2.0 but I don't know if those providers allow it because that flow doesn't require the application to identify itself.

I think you pretty much got it. The authorization grant flow would be something like this: enter image description here

The password grant flow would be pretty much the same, but with out the redirect and authorization steps. You would just login with your own form and have the server make the auth request to the provider using the password grant type.

If you're just using it for authentication only, then you wouldn't be making a request with that particular access token to their resource server. I'd need to know more about your architecture to say more. However, generally, if you have an internal identity provider that handles roles and identity, you might consider a federated identity provider that can transform 3rd party tokens into your internal format and store that along with the 3rd party token. That way you can still make requests to the 3rd party if needed and still have what you need to move around internally if that makes sense. If that's even a concern, let me know and I'll explain that leg too.

Idiocrasy answered 31/5, 2014 at 7:24 Comment(0)
B
1

Forms auth usually puts a cookie to the authenticated user, so what you can do is do the same, and send the exact same cookie that forms auth would have sent.

So, on sucessfull OAuth callback from the provider, you can just do something like this:

  // here, we are called on a successful OAuth auth, so 
  // let's do Forms login by ourselves
  HttpCookie authCookie = GetFormsAuthCookie(email, true, true);
  context.Response.Cookies.Add(authCookie);

With the GetFormsAuthCookie method defined like this:

  private static HttpCookie GetAuthCookie(string userName, bool createPersistentCookie, bool httpOnly)
  {
      FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(2, userName, DateTime.Now, DateTime.Now.Add(FormsAuthentication.Timeout), createPersistentCookie, "SocialEmailLogin", FormsAuthentication.FormsCookiePath);
      string encryptedTicket = FormsAuthentication.Encrypt(ticket);
      if (encryptedTicket == null)
          throw new Exception("Obviously, something went wrong here. That shouldn't happen.");

      HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
      cookie.HttpOnly = httpOnly;
      cookie.Path = FormsAuthentication.FormsCookiePath;

      if (FormsAuthentication.RequireSSL)
      {
          cookie.Secure = true;
      }

      if (FormsAuthentication.CookieDomain != null)
      {
          cookie.Domain = FormsAuthentication.CookieDomain;
      }

      if (ticket.IsPersistent)
      {
          cookie.Expires = ticket.Expiration;
      }
      return cookie;
  }
Burnisher answered 26/5, 2014 at 10:36 Comment(4)
The answer that i'm looking for can be a high level one, more related to the high level flow. How do you propose protection against a malicious request that, falsely notifies me that a OAuth provider auth a user ?Nakashima
Please enhance your question. What you want is not clear at all. IF you're looking on how to secure oauth, you can go for the standard that contains a lot of input: tools.ietf.org/html/draft-ietf-oauth-v2-25#section-10Burnisher
You are correct,the security part it's a bit of a scope creep, but my question is "What solutions are out there for combining a Form auth with a OAuth auth ?". I don't see your answer providing a new solution, you just provide an implementation for the bottom part "Here is your auth ticket APPTK1234". Are you saying there is no need for validating the ticket from the provider? or validating is the only option? aren't there solutions that might imply a different flow on the client/server? (note: when I say form auth, I'm referring to User/Password, not .Net FormsAuthentication )Nakashima
Also, for your own benefit, I'd like to point out that the OAuth provider doesn't issue a ticket, it issues a token; two different things. Also, username/password isn't "form auth" in the OAuth realm. I believe what you're looking for is simply the password grant type or "Resource Owner Password Credentials Grant" (section 4.3 of the spec). I think those two things could help reduce confusion and ambiguity as well as help you on your search.Idiocrasy

© 2022 - 2024 — McMap. All rights reserved.