locked
How to Combine Google ( or other) Authentication & Windows Authentication RRS feed

  • Question

  • User369345748 posted

    Suppose our front end app allows users to login with a Google credential,  & but the web API also requires access to server resources or web services that need Windows Authentication to access them.  Is there a way to make the call to those other resources temporarily run with the App Pool Id ,  like impersonation in reverse?  

    Friday, August 11, 2017 9:49 AM

All replies

  • User475983607 posted

    Suppose our front end app allows users to login with a Google credential,  & but the web API also requires access to server resources or web services that need Windows Authentication to access them.  Is there a way to make the call to those other resources temporarily run with the App Pool Id ,  like impersonation in reverse?  

    The application always runs under the application pool account.  Can you be more specific as to the problem you are trying to solve?

    Friday, August 11, 2017 10:27 AM
  • User369345748 posted

    Thanks for the quick response.

    In an application with a UI tier and an API layer running with Windows Authentication, where that API itself calls on other external APIs or resources (EG SharePoint) its easy enough to use Windows Authentication with Kerberos to pass the logged in credential throughout  the entire process ( UI >>> API,   API >>> to other Resources) .  That credential can be in AD groups & can be authorised directly where ever it is needed. 

    In a world with Google Auth, I cant do that.

    I have seen several examples for Google ( other logins are available) authentication to basic MVC or SPA, where there is 1 layer of application only.

    I need to do two things :

    1) to pass the Google credential from the UI tier through to the myAPI ( eg logging that DVader123@google.com  has visited this function , & checking that they are authorised to run that api function., through a custom authorisation mechanism.   

    2) call other existing services or resources which require windows authentication & which will not authorise DVader123., but will be happy to authorise MyDomain\MyAppPool id

    So in myAPI, when I'd run the other services or access sharepoint instead of using webclient.usedefaultcredentials  or Credentialcache.DefaultCredentials, as I would with WindowsAuth (& which I think would be DVader123),   I could set WebCleint.credentials to 'MyDomain\MyAppPool id' instead.  

    I have tried the following elements on local  & they are mostly returning empty structures

    var winPrip = WindowsPrincipal.Current;
    var winId = WindowsIdentity.GetCurrent();
    var GenId = GenericIdentity.DefaultNameClaimType;
    var impersonationContext = WindowsIdentity.Impersonate(IntPtr.Zero);

    Friday, August 11, 2017 11:18 AM
  • User1168443798 posted

    Hi Richard,

    >> but the web API also requires access to server resources or web services that need Windows Authentication to access them.

    For Windows Authentication, I think you need to Host Web API under user credential account instead of App Pool. In this way, no matter who calling the API, the Web API will use the user account to call external resource.

    If you do not want to run the web api under specific account, I think you could try impersonate to call resource from Web api, and you could refer below link.

    #https://forums.asp.net/t/2126720.aspx?Access+Denied+while+reading+writing+directory+in+Network+File+Share+through+Service+Account

    Best Regards,

    Edward

    Monday, August 14, 2017 5:36 AM
  • User369345748 posted

    Hi Edward

    Thanks for this.   

    How should I be configuring the the Client credentials  ( using WebClient)  to run the web service ?   At the moment I am getting access denied, 

    Tuesday, August 22, 2017 9:19 AM
  • User1168443798 posted

    Hi Richard,

    Which code did you use?

    Will it work like below:

    client.UseDefaultCredentials = true;

    Or

    client.Credentials = new NetworkCredential("username", "password");

    Best Regards,

    Edward

    Tuesday, August 22, 2017 9:53 AM
  • User369345748 posted

    Hi Edward 

    Thanks for the reply.

    I have tried with the  useDefaultCredentials  - no Joy

    I am avoiding putting in an ID / Password.  I thought that was the point of Google Auth Tokens. User ID / Password goes into google only, & I get a time limited token back, which I pass to the Web API, then I let the Web API talk to Google ( with the token) to see who it thinks the token belongs to.   

    I would have though that this was a common enough scenario.

    Tuesday, August 22, 2017 10:26 AM
  • User475983607 posted

    AFAIK, it is not possible to have Windows Authentication and Google Authentication at the same time in a single application.  As you have seen there is no automatic fallback method.  

    You could use Windows authentication and Google authentication to create a central custom token.  The 40,000 foot view, Create an Windows app entry point.  If the user is authenticated, then contact the custom token service and get a token that indicates the user is windows authenticated.  If windows authentication fails, redirect the user to the Google login.  If the user authenticates with Google, contact the custom token service for a Google auth token.   Use the custom token for authentication.

    Tuesday, August 22, 2017 11:35 AM
  • User1120430333 posted

    Why wouldn't you use two different app pools for the various services and required authentication?

    Tuesday, August 22, 2017 12:11 PM
  • User369345748 posted

    At the moment, I am having trouble making the UI Layer call the Web Service with the the Google credential, it has authenticated with

    When I was using Windows Auth with Kerberos, it was simple enough to pass my credential across by setting WebClient.UseDefaultCredentials = true;  , but this does not appear to work.   I have a feeling I must be doing something wrong, as it should nt be this complex.

    Tuesday, August 22, 2017 1:04 PM
  • User475983607 posted

    When I was using Windows Auth with Kerberos, it was simple enough to pass my credential across by setting WebClient.UseDefaultCredentials = true;  , but this does not appear to work.   I have a feeling I must be doing something wrong, as it should nt be this complex.

    I believe it is because DefaultCredentials applies to NTLM, negotiate, and Kerberos-based authentication not Google.  You'll need to pass the Google token to the service and the service will need to know how to handle the token.

    Tuesday, August 22, 2017 7:25 PM
  • User369345748 posted

    Thanks for this.  In terms of actually launching the Service you said  

    You'll need to pass the Google token to the service and the service will need to know how to handle the token.

    Is this a question of manually parsing out the token from the last request or the session , & manually injecting the result as a header or a querystring value, or is there something a little more elegant ? This should be a common enough use case.

    Wednesday, August 23, 2017 6:11 AM
  • User475983607 posted

    Is this a question of manually parsing out the token from the last request or the session , & manually injecting the result as a header or a querystring value, or is there something a little more elegant ? This should be a common enough use case.

    I have not used Google authentication but I assume it works like forms authentication where the token is stored inside a cookie.  Browser pass cookie automatically on each request. Therefore you should be able to forward the cookie to the Web API similar to how a browser works. The HttpClient has cookie container for doing this type of thing.  

    https://rivdiv.wordpress.com/2015/07/15/passing-cookies-to-asp-net-webapi-via-httpclient/

    Of course the Web API needs to expect the cookie.

    Wednesday, August 23, 2017 11:06 AM
  • User369345748 posted

    Thanks for this 

    I have been able to pass across all my cookies to the web API, but unfortunately the google auth token is not in the normal   Request.Cookies   collection.   Neither can I find an object tagged as "authToken" .    I am not 100% sure where to find it !

    Wednesday, August 23, 2017 2:32 PM
  • User1168443798 posted

    Hi Richard,

    Please help to check whether below description is right.

    1. You have a UI tier which will login by Google account

    2. You have a web api project which enables Google authentication, there is no problem to call web api method.

    3. Call other service which enables Windows authentication from Web API method, and you got unauthorized when calling other services.

    If so, your Google credential will not work for other services. Windows authentication needs the domain credentials. There is no way to make Google account works for Windows authentication.

    Per to your description, you run web api under appPoll account, I suggest you try to run web api under user account which has permission to other service. “MyDomain\MyAppPool” would not work for windows authentication.

    Best Regards,

    Edward

    Friday, August 25, 2017 7:26 AM
  • User369345748 posted

    Hi Edward

    Thanks for the reply.  

    1) At the moment I have a UI tier which I login via google & I am successfully authenticating to.   

    2) I have an API tier which I WANT to authenticate to, using the Google credential (above), but....   

    2.1)  I  dont know how to get at the Google Authentication token from point 1.   Where is it stored? 

    2.2) If I could get hold of it I dont know what the best mechanism is for passing it to the REST WEBAPI 2.0 tier ( Querystring, headers etc.).

    2.3) When the REST WEBAPI 2.0 receives the token data, how do I do anything useful with it?  Do I extract the details from it, & just trust it, or do I pass it off to google to confirm that the token is current & valid for the user it claims to be from?

    2.4) Do I have to do this manually or is there a  set of existing classes( EG. WebClient, HttpClient) , that can handle all of this cleanly? 

    3) Once I have reached the REST WEBAPI 2.0 tier & it knows its being run by GenericUser@Google.somewhere, then that API will also need to call a second set of restServices (intranet API) which use Windows authentication - so I am assuming that myDomain\AppPoolId will be credential for that  

    Thanks again 

    Richard

    PS at the moment plan B is to generate my own token in the UI & pass it as normal parameter from the API, & revalidate it there.  EG

    string validationtoken = MySecretValidationTokenFormula(emailaddress);

                                             // returns a8b64babd0aca91a59bdbb7761b421d4f2bb382........etc.

    & pass it as "api/myFunc?email="+email+"&token="+validationtokenVal"

                                             //api/myFunc?email=GenericUser@Google.somewhere&token=a8b64babd0aca91a59bdbb7761b421d4f2bb382..........

    Then in the api 

    apiExpectedTokenVal = MySecretValidationTokenFormula(email);

    & compare apiExpectedTokenVal  with validationtokenVal

    Friday, August 25, 2017 8:56 AM
  • User1168443798 posted

    Hi Richard,

    >> I have an API tier which I WANT to authenticate to, using the Google credential (above), but

    Which authentication did you use for API? If you use windows authentication for API, there is no way to use Google credential.

    Best Regards,

    Edward

    Friday, August 25, 2017 9:15 AM
  • User369345748 posted

    Hi Edward

    The REST API is configured for Google Auth : 

    public class SecurityConfig
    {
    public static void Configure(IAppBuilder app)
    {
    // Enable the application to use a cookie to store information for the signed in user
    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
    AuthenticationType = DefaultAuthenticationTypes.ExternalCookie
    });

    // Use a cookie to temporarily store information about a user logging in with a third party login provider
    app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

    // Configure google authentication
    var options = new GoogleOAuth2AuthenticationOptions()
    {
    ClientId = "yyyyyyyyyyyyyyyyyyyyyyy",
    ClientSecret = "xxxxxxxxxxxxxxxxxxxxx"
    };

    app.UseGoogleAuthentication(options);
    }
    }

    Friday, August 25, 2017 9:31 AM
  • User1168443798 posted

    Hi Richard Scan,

    >> I  dont know how to get at the Google Authentication token from point 1.   Where is it stored?

    Do you mean you want to authenticate Web API by the token from UI tier? Are the UI and web api in the same application? If not, I think it is impossible. We could not authenticate the second application by token from application one. The token is specific to the application. You will need to re-request the token for web api application which means you need to process another Google authentication for Web API.

    Best Regards,

    Edward

    Monday, August 28, 2017 8:00 AM
  • User369345748 posted

    Hi Edward

    I had been assuming that these would be two different apps, within the same domain;  Apps.MyOrg/UItier  and Apps.MyOrg/Api/RestStuff, & that this would be enough for authentication(like Kerberos / Windows) .  I am no sure how well it would work combining a WebAPI2.0 & MVC UI into a single application without an awful lot of tweaking and breaking.  

    But suppose I built Apps.MyOrg/UItier as a traditional MVC app and shoehorned an API controller into it, how would I invoke that rest controller?  Would I go for a traditional MVC approach ( Eg a redirect to action) or a REST call? 

     Thanks Richard

    Tuesday, August 29, 2017 7:01 AM
  • User1168443798 posted

    Hi Richard,

    >> how would I invoke that rest controller?  Would I go for a traditional MVC approach ( Eg a redirect to action) or a REST call?

    What do you mean by this? Do you want to invoke Rest Controller from View or Controller?

    If it is from View, you could try rest call like Ajax request.

    If it is from Controller, I am wondering the reason you want to redirect a request from MVC Controller to Web API Controller. You total could request the Web API controller directly from View. MVC Controller usually returns View instead of Only data.

    Best Regards,

    Edward

    Wednesday, August 30, 2017 8:22 AM