4

I am trying to call the RegisterExternal method in Web API, after having retrieved a token from facebook. But I keep getting a 401 Unauthorized from my Web API. I am not sure I am correctly implementing the logic flow. My code is;

Ask for supported external login providers;

    public async Task<List<ExternalLoginViewModel>> GetExternalLoginsAsync()
    {
        using (var client = GetNewHttpClient(false))
        {
            var response = await client.GetAsync("api/account/externalLogins?returnUrl=/&generateState=true");

            response.EnsureSuccessStatusCode();

             return await response.Content.ReadAsAsync<List<ExternalLoginViewModel>>();
        }
    }

From this, I am returned a facebook URL. I follow this and then enter in my facebook username and password. I return back to my app via a deep link and then try and call the RegisterExternal method in the web API like this, passing the facebook "access token" that is returned.

    public async Task<bool> SendSubmitRegisterExternalAsync(RegisterExternalBindingModel ro, string accessToken)
    {
        using (var client = GetNewHttpClient(true))
        {
            client.DefaultRequestHeaders.Add("Authorization", String.Format("Bearer {0}", accessToken));

            HttpResponseMessage response = await client.PostAsJsonAsync("api/Account/RegisterExternal", ro);
            if (response.IsSuccessStatusCode) return true;

            var value = await response.Content.ReadAsStringAsync();
            throw new ResponseErrorException(ErrorHelper.GetErrorString(value));
        }
    }

I receive 'Unauthorized' every time. I do not know what is wrong. My Web API method looks like this, and the class is marked with the [Authorize] attribute.

    [OverrideAuthentication]
    [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
    [Route("RegisterExternal")]
    public async Task<IHttpActionResult> RegisterExternal(RegisterExternalBindingModel model)
    {
        ...

I have found three different posts this evening of people asking this exact same question, and in all cases there are no replies, so I am not hopeful but if anyone can shed some light on this it would be great!

EDIT: I have also changed the method signature to 'allowanonymous' and still get unauthorized!

    [OverrideAuthentication]
    [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
    [AllowAnonymous]
    [Route("RegisterExternal")]
    public async Task<IHttpActionResult> RegisterExternal(RegisterExternalBindingModel model)
    {
creatiive
  • 1,073
  • 21
  • 49

1 Answers1

1

I have sorted this by not using FacebookSessionClient and doing it via a WebBrowser control instead.

I use the URL from the first step (provided to me by the WebAPI). Then on the Navigated event from the WebBrowser control, i parse the Url for the access token;

    public async void ParseUrlForAccessToken(string url)
    {
        string fieldName = "access_token";
        int accessTokenIndex = url.IndexOf(fieldName, StringComparison.Ordinal);

        if (accessTokenIndex > -1)
        {
            int ampersandTokenIndex = url.IndexOf("&", accessTokenIndex, StringComparison.Ordinal);
            string tokenField = url.Substring(accessTokenIndex, ampersandTokenIndex - accessTokenIndex);
            string token = tokenField.Substring(fieldName.Length);

            token = token.Remove(0, 1);

            await _dataService.SubmitLoginExternal("Test", token);

        }
    }

Then as shown above, I call SubmitLoginExternal, which is a call to the following code which uses the access token retrieved from the WebBrowser control Url to register the account (in this case a 'Test' account);

        using (var client = GetNewHttpClient(true))
        {
            client.DefaultRequestHeaders.Add("Authorization", String.Format("Bearer {0}", accessToken));

            HttpResponseMessage response = await client.PostAsJsonAsync("api/Account/RegisterExternal", ro);
            if (response.IsSuccessStatusCode) return true;

            var value = await response.Content.ReadAsStringAsync();
            throw new ResponseErrorException(ErrorHelper.GetErrorString(value));
        }

This has worked and now I have the user registered in my database.

The key was to use a WebBrowser control and not the FacebookSessionClient object or a WebBrowserTask. You cannot use a WebBrowserTask as you need to hook in to the navigated event once the page has loaded to call ParseUrlForAccessToken().

creatiive
  • 1,073
  • 21
  • 49