Open Closed

Using ExternalBearer across all application: WebApi & Web #501


0
efijeremiah created

Hi there,

Thanks for your quick responses on my previous questions. In the template there are 2 projects:

  1. .WebApi
  2. .Web

currently the situation is that : .Web project uses Cookie Token and .WebApi uses ExternalBearer Token

its configured under Startup.cs file. I need all my client application weather its the .Web application and other client application that i write to work with ExternalBearer cause that's the right way to go.

I've tried to edit Startup.cs file to support that as follows..i'm getting the the ExternalBearer after the call but the when i try to preform an Authorized API call with the ExternalBearer Token i got i'm getting an error message that the "User is not logged in", please your asap advice what am i doing wrong:

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.UseOAuthBearerAuthentication(AccountController.OAuthBearerOptions);

        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            //AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            AuthenticationType = DefaultAuthenticationTypes.ExternalBearer,
            LoginPath = new PathString("/Account/Login")
        });

        //app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalBearer);

        if (IsTrue("ExternalAuth.Facebook.IsEnabled"))
        {
            app.UseFacebookAuthentication(CreateFacebookAuthOptions());                
        }

        if (IsTrue("ExternalAuth.Twitter.IsEnabled"))
        {
            app.UseTwitterAuthentication(CreateTwitterAuthOptions());                
        }

        if (IsTrue("ExternalAuth.Google.IsEnabled"))
        {
            app.UseGoogleAuthentication(CreateGoogleAuthOptions());                
        }
    }

    private static FacebookAuthenticationOptions CreateFacebookAuthOptions()
    {
        var options = new FacebookAuthenticationOptions
        {
            AppId = ConfigurationManager.AppSettings["ExternalAuth.Facebook.AppId"],
            AppSecret = ConfigurationManager.AppSettings["ExternalAuth.Facebook.AppSecret"]
        };

        options.Scope.Add("email");
        options.Scope.Add("public_profile");

        return options;
    }

    private static TwitterAuthenticationOptions CreateTwitterAuthOptions()
    {
        return new TwitterAuthenticationOptions
        {
            ConsumerKey = ConfigurationManager.AppSettings["ExternalAuth.Twitter.ConsumerKey"],
            ConsumerSecret = ConfigurationManager.AppSettings["ExternalAuth.Twitter.ConsumerSecret"]
        };
    }

    private static GoogleOAuth2AuthenticationOptions CreateGoogleAuthOptions()
    {
        return new GoogleOAuth2AuthenticationOptions
        {
            ClientId = ConfigurationManager.AppSettings["ExternalAuth.Google.ClientId"],
            ClientSecret = ConfigurationManager.AppSettings["ExternalAuth.Google.ClientSecret"]
        };
    }

    private static bool IsTrue(string appSettingName)
    {
        return string.Equals(
            ConfigurationManager.AppSettings[appSettingName], 
            "true",
            StringComparison.InvariantCultureIgnoreCase);
    }
}

8 Answer(s)
  • 0
    hikalkan created

    Hi,

    Just remove these lines from Startup.cs:

    app.UseCookieAuthentication(new CookieAuthenticationOptions
                {
                    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                    LoginPath = new PathString("/Account/Login")
                });
    
                app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
    

    Do not modify other code.

    I did it and I can use token based auth from Postman (as described here: <a class="postlink" href="http://www.aspnetzero.com/Documents/Development-Guide#token-based-authentication">http://www.aspnetzero.com/Documents/Dev ... entication</a>) But I could not login from user interface, as expected. From now, we should login by token based auth and include the token in every web request.

    BUT... I don't think that cookie auth is wrong for web UI. Instead, it's more common and natural way for browsers. Why do you think like that?

  • 0
    efijeremiah created

    the scenario i'm facing is as follows: i have several client applications including: Chrome extension, firefox extension, the web application and future mobile application

    On the Chrome extension i need to use the Web Application screens for Login/External Login/Register/Password Reset etc..therefore i need 1 method for login/register/prefor webAPI calls. from what i read and know Bearer is the right way to go.

    currently i can use the WebAPI perfectly using bearer but only for login (no register/external login methods). I tried what you've suggested and as expected the Web app doesn't work anymore. After day of trial and error no luck, the closest i got is through this post: <a class="postlink" href="http://stackoverflow.com/questions/23262471/use-owin-ws-federation-package-to-authenticate-against-adfs-3-0">http://stackoverflow.com/questions/2326 ... t-adfs-3-0</a>

    adding JUST this line at the beginning of the Configuration method: app.SetDefaultSignInAsAuthenticationType(DefaultAuthenticationTypes.ExternalBearer);

    that allowed me to read the login page but after logging in - i got an unauthorized message.

    Please your quick help :oops:

  • 0
    efijeremiah created

    Alternatively, the last option i had in mind is to use the ApplicationCookie as it's configured originally on Startup.cs and call from another client (postman for example) to the WebApi just like you do with the bearer. But in this case, i keep getting the same error that the user is not logged in. even though i've tried to play with the Cookie parameters on Postman and made my Cookie persistence by editing:

            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                LoginPath = new PathString("/Account/Login"),
                ExpireTimeSpan = TimeSpan.FromDays(100000.0) //HAS TO BE A DECIMAL VALUE. IF NOT, WILL NOT WORK!
            });
    

    As previously noted, I prefer working all the way with bearer on all client applications. But in the current situation please you advice how can i access the GetUsers for example using Cookie instead of bearer ?

  • 0
    hikalkan created

    Hi,

    I tried what you've suggested and as expected the Web app doesn't work anymore.

    Yes it does not work, since Web app uses Cookie based auth. You should replate register/login system and also send token in the header for every ajax request. Even you send it for ajax, I don't know how to set token in the header for non-ajax requests (For example, for a regular MVC page with browser's get request). So, I strongly suggest to keep cookie based auth for web app, otherwise you will make many changes which I also don't know.

    app.SetDefaultSignInAsAuthenticationType(DefaultAuthenticationTypes.ExternalBearer);

    Do not do it since this may break cookie auth.

    ...i keep getting the same error that the user is not logged in. even though i've tried to play with the Cookie parameters on Postman and made my Cookie persistence by editing

    Cookie method is not proper for Postman and other clients. But I did implement it before from an c# console application: <a class="postlink" href="https://github.com/aspnetboilerplate/aspnetboilerplate-samples/tree/master/ConsoleRemoteWebApiCall">https://github.com/aspnetboilerplate/as ... WebApiCall</a>

    As you see, I call Login and get cookies (<a class="postlink" href="https://github.com/aspnetboilerplate/aspnetboilerplate-samples/blob/master/ConsoleRemoteWebApiCall/CallApiFromConsole/Program.cs#L127">https://github.com/aspnetboilerplate/as ... am.cs#L127</a>) then using these cookies for next web request (<a class="postlink" href="https://github.com/aspnetboilerplate/aspnetboilerplate-samples/blob/master/ConsoleRemoteWebApiCall/CallApiFromConsole/Program.cs#L113">https://github.com/aspnetboilerplate/as ... am.cs#L113</a>)

    This is also possible for a mobile application, but not preferred way. Tokens are easier to implement for other clients.

    If you need to to a register method for other clients, you can implement it in web api controller or you can even call AccountController's Register method (since this method does not require authentication).

    I don't know how to handle external auth with a token auth and a mobile client. You can search web for it, since these are not much AspNet Zero specific stuff. Actually, our token based auth implementation is not AspNet Zero specific (I implemented it reading this article: <a class="postlink" href="http://bitoftech.net/2014/06/01/token-based-authentication-asp-net-web-api-2-owin-asp-net-identity/">http://bitoftech.net/2014/06/01/token-b ... -identity/</a>).

  • 0
    tteoh created

    Hi,

    I'm doing prevent multiple login and it's working fine now. But I've a question about it, which is can I prevent the multiple login no matter it's from browser or other agents (such as Postman)?

    Thanks. /Tommy

  • 0
    ismcagdas created

    Hi @tteoh,

    Can you explain how do you prevent multiple logins ? We can suggest somnething accordingly.

    Thanks.

  • 0
    tteoh created

    <cite>ismcagdas: </cite> Hi @tteoh,

    Can you explain how do you prevent multiple logins ? We can suggest somnething accordingly.

    Thanks.

    Hi @ismcagdas,

    This: [https://forum.aspnetboilerplate.com/viewtopic.php?f=5&t=6729&p=22492#p22492])

    Thanks. /Tommy

  • 0
    ismcagdas created

    Thanks @tteoh,

    I see now, but AspNet Zero does not offer a solution for this. Since this is a common identity use case, maybe you can find an answer on the web.

    Thanks.