Base solution for your next web application
Open Closed

OAuth 2 External Social Login #3225


User avatar
0
ribbo created

Hi, Using Angular 2 what do you recommend is the best way to implement an OAuth 2 external login? The site is Strava, <a class="postlink" href="https://strava.github.io/api/v3/oauth/">https://strava.github.io/api/v3/oauth/</a>

My problem is your implementation of Facebook and Google login uses their JS library to do get the accessToken, however this site doesn't provide any kind of pre-built JS SDK like that.

I did have this working previously on aspnetboiler plate with AngularJS by using OWIN (there is a pre-build OWIN middleware for the above Strava site), but this used MVC based Account login. But I don't know how I would add the same methods with the new Angular 2 architecture or if that is the best way to try go.

Thanks, Matt


18 Answer(s)
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    When developing angular2 version, we think angular2 side as a totaly seperatead pure client side app and that is why we used this approach. I don't know if there is another way for pure angular2 apps.

    Have you asked this to strava ? I think they can suggest you the best way for using strava with angular2.

    Thanks.

  • User Avatar
    0
    ribbo created

    Hi, I have found a Strava OAuth provider via <a class="postlink" href="https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers">https://github.com/aspnet-contrib/AspNe ... .Providers</a>

    This is working perfectly when add to the aspnet zero MVC Core project. I have tried to migrate over the AccountController to the Angular 2 project, this way I can use MVC just to provide the 3rd party login\registration.

    Everything seems to work correctly, I can see AspNet.Security.OAuth.Strava getting all the user details in the CreateTicketAsync function. The function ExternalLoginCallback gets called but the problem is within this function the externalLoginInfo is always null.

    var externalLoginInfo = await _signInManager.GetExternalLoginInfoAsync(); always returns null.

    I think this might be an issue with Cookie External Authentication, is there something I am missing to get this to work in the Core/Angular project?

    Thanks, Matt

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    I think you need to implement a class like this for strava, <a class="postlink" href="https://github.com/aspnetzero/aspnet-zero-core/blob/master/aspnet-core/src/MyCompanyName.AbpZeroTemplate.Web.Core/Authentication/External/Facebook/FacebookAuthProviderApi.cs">https://github.com/aspnetzero/aspnet-ze ... iderApi.cs</a>.

    Please let us know if it does not work.

    Thanks.

  • User Avatar
    0
    ribbo created

    Hi, This won't work as it requires all the OAuth logic to be implemented via the Angular UI? There is no Javascript SDK for Strava OAuth like there is for Facebook\Google.

    The reason I have decided to implement the MVC controller\authentication from the aspnet zero MVC project is because there is one written for .NET MVC based AspNet.Security.OAuth which is AspNet.Security.OAuth.Strava. This works PERFECTLY under your MVC project. So its easier to just add the MVC controller to the Angular project just for the sign in (similar to how you had the original Angular JS working).

    I also tried to add the Google authentication via MVC to ensure it isn't my Strava OAuth. I did this with AuthConfigurer.cs by adding. app.UseGoogleAuthentication(new GoogleOptions { ClientId = "{myClientId}", ClientSecret = "{mySecret}" }); This had the exact same result, everything worked except the external login info returns null. var externalLoginInfo = await _signInManager.GetExternalLoginInfoAsync(); always returns null.

    So what I need to know, what do I need to add to the Core\Angular project to get the MVC External Login to work? From what I can tell all the StartUp.cs is nearly the same between Angular and MVC projects.

    Thanks, Matt

  • User Avatar
    0
    ribbo created

    To clear 1 thing up... when I talk about your MVC Project, I mean the "ASP.NET CORE MVC & Jquery". I have essentially copied over the AccountController to manage the external OAuth login.

  • User Avatar
    0
    hikalkan created
    Support Team

    Hi Ribbo,

    I'm just joining to discussion to help you.

    The main difference between MVC UI (AspNet Core + jQuery) from Angular UI (AspNet Core + Angular4) is that MVC application uses cookie authentication, but Angular uses token based authentication, which makes flow completely different. The reason Angular UI uses tokens (not cookies) is that cookies does not work properly for cross domain requests.

    We also had problems while implementing Facebook & Google authentications and have written many custom (but actually standard-compatible) code and spend a lot of time to accomplish it. For instance, we could not do Microsoft auth since it does not provide a proper js client. Auth is not an easy thing :)

    So, what you should first do to contact to strava support to ask how you can authenticate a plain HTML Angular application and obtain an access token. In the end, strava is a 3rd party provider. After they lead you, we will glad to help you further if you have a problem specific to AspNet Zero codebase.

  • User Avatar
    0
    ribbo created

    That makes sense as all my research pointed to Cookie Authentication not being setup correctly in StartUp used to get the External Login detail. While I understand the reason in terms of having login via Angular needing Token Authentication. Is there a way to enable Cookie Authentication for the MVC side so this flow works and also have Token Authentication at the same time in the same solution? There isn't any JS library I can find provided by Strava which means implementing my self (which I would prefer not to do same reason as you have for Microsoft).

    The flow I was thinking (confirm if this will or won't work), if I can turn on Cookie Authentication for MVC in the same project along side :

    1. User hits Angular Client where there is a "Sign in to Strava" button eg. <a class="postlink" href="http://www.mysite.com">www.mysite.com</a>
    2. Button takes them to login.mysite.com/login/strava. This will be a separate subdomain where the API\MVC is.
    3. MVC takes over OAuth login and returns them to login.mysite.com/login/ExternalLoginCallback
    4. ExternalLoginCallback gets details via Cookie Authentication with signInManager.GetExternalLoginInfoAsync(); and registers the user if it doesn't exist
    5. If user exists login via Token authentication and return them back to <a class="postlink" href="http://www.mysite.com">www.mysite.com</a> Angular site logged in with the Token

    The flows seems to be almost the same as the old .NET\Angular JS (before Angular 2 project) where MVC was used for authentication and Angular for the rest. Currently I have everything above working up to step (4) where it fails to get the LoginInfo due to the cookie authentication. If you can tell me how to turn on Cookie Authentication I think everything will work for me.

    Thanks, Matt

  • User Avatar
    0
    ribbo created

    Hi Hikalkan, Would love some further guidance on this.

    Thanks, Matt

  • User Avatar
    0
    hikalkan created
    Support Team

    As long as they are in the different domain, Cookie authentication will not work.

    Cookie auth is already enabled for the .Host project, if you are asking for it? But angular can not use it (because of cross domain).

    If you can login use with the MVC side and register the new user, then you may try to pass a temporary token to the angular side. Angular then requests to server with the token, authenticates and gets an actual token. We will make a similar thing in this release to seperate Public Web Site and make single sign on with angular application.

    One another option can be merging angular to the MVC/Host solution and change angular side to use cookie based auth.

    I would want to help you clearer, but this goes to a custom development work. If I would work on that I would would have many different problems and solve one by one and spend significiant time to make a working solution. So, it's not easy to write a step by step TODO for you unless we work on that deeply.

  • User Avatar
    0
    ribbo created

    Thanks for the info. Your option here is exactly what I am trying to do "If you can login use with the MVC side and register the new user, then you may try to pass a temporary token to the angular side. Angular then requests to server with the token, authenticates and gets an actual token."

    The problem I am having is that the function call signInManager.GetExternalLoginInfoAsync() is returning NULL. This is not using the Angular side at all, just MVC domain\url directly. So all communication is within the same domain, but for some reason it some back NULL. This is for Google login as well for testing. Everything works correctly within the actual MVC package when I download it. So wondering if there is any setting I need to change for the Angular downloaded package?

    Thanks, Matt

  • User Avatar
    0
    ribbo created

    Also when is your next release out? As it sounds like it will have exactly what I am looking for in it.

    Thanks, Matt

  • User Avatar
    0
    hikalkan created
    Support Team

    Next release will be in 2-3 weeks. BTW, the code you are looking for will be completed in our Github repository in a few days.

    I suppose you are using angular2 version where there is no MVC code. So, how do you have the MVC project? Have you created another MVC project (with jquery version) with same name and copied Web.Mvc part? Or did you build it yourself? I'm asking this because Google auth is working as expected when you create MVC & jquery solution.

  • User Avatar
    0
    ribbo created

    Great news, will keep an eye out on the repository.

    MVC Core + JQuery solution works perfect.

    Core + Angular 4 works but fails to get externallogindetails on call back (this is by calling MVC controller directly in browser not interacting with Angular at all). Assumed Cookie issue.

    I have just added a new controller to Web.Host called "AuthenticationController", which is basically the same as the AccountController from the MVC Project.

    So that raises a big question and where maybe my issue is. This controller is sitting within Web.Host, I have not added a whole new project called Web.Mvc. Is there differences in Web.Host VS Web.Mvc that would stop this from working?

    So my StartUp/AuthConfigure.cs has this code in Web.Host app.UseGoogleAuthentication And the controller added to Web.Host. The controller\login works perfectly until ExternalLoginCallback is called with _signInManager.GetExternalLoginInfoAsync just gets NULL. I am now wondering if this is because it is all sitting within the Web.Host project and not a new Web.Mvc project from the MVC solution.

    Is there a way to get Web.Host to work for this as I don't really want to have a separate project that needs to be run (1 for API and separate 1 for MVC).

    Thanks, Matt

  • User Avatar
    0
    hikalkan created
    Support Team

    Hi,

    Web.Mvc project covers Web.Host project. It also can serve all API to Angular UI. But we delete in project creation. What can you do that:

    1. Create a new project with same company/project name with aspnet core + jquery. Notice that you should select the same version with your aspnetcore + ng project.
    2. Copy .Web.Mvc project to your existing solution. Thus, you will have a second UI, with jQuery & MVC based.
    3. Configure server side endpoints for angular UI since Web.Mvc project runs in a different port.
    4. Configure Cors like in Web.Host project.

    These are what I remember. Check Web.Host project's source code and configuration if anything we missed. Once you can use Web.Mvc as your server, you can delete Web.Host project. If you like, you can also delete application UI (App Area) from Mvc project. I suppose you are using a source control system, otherwise remember to back up before any change.

  • User Avatar
    0
    ribbo created

    Hi, I have upgraded to 4.1.4 and see the Single Sign On method via a temporary token, but it is the other way round than I hoped. It still uses all the Angular Login and then passes back for Sign Sign On to the MVC site. Is it possible to do it the other way around and login via MVC and then pass Single Sign On Token across to the Angular project?

    Thanks, Matt

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @Ribbo,

    Yes, you can implement that as well but in that case you will need to develop Login, Register, Email Activation, Password Reset pages for frontend MVC project.

    After that, you can send token to angular and login user in angular project with that token if you like.

    Can you also explain why you want to implement opposite way ?

    Thanks.

  • User Avatar
    0
    ribbo created

    Hi, I have actually got this all working. Steps was to copy the MVC project into my Angular solution from the MVC\JQuery solution. This gives me all the login requirements and Single Sign On token generation. Then added to the Angular Web.Core project to TokenAuthController a SingleSignOnAuthenticate function. This is then essentially the same as the Public website SSO login mixed with the Authenticate function. The key I found was to get the Identity which I used var identity = (ClaimsIdentity)(await _principalFactory.CreateAsync(user)).Identity; In the Angular side I just pass the SSOToken etc. into this function for SSO login.

    It then worked perfectly to login from MVC login through to Angular application.

    The reason I needed to do this is because the Angular application uses a very different Javascript based login for Social sites like Facebook, part of the reason you have issues with Microsoft login. I needed to sign into a different site Strava using OAuth2 that also can't be done easily via javascript. But it is easy to implement via the MVC project (I already had that working). So now I use the MVC project for Just logging into Strava via OAuth 2 and then SSO into the Angular project.

    It works nicely now.

    Thanks, Matt

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @Ribbo,

    Now I remember Strava :). Thanks a lot for your feedback and detailed explanation.