Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 422 Vote(s) - 3.5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Web API / OWIN, SignalR & Authorization

#1
I am developing a prototype of an AngularJS, Web API, SignalR application as a potential starting point for a new project in VS 2013.

At this stage, I'm pretty much using the canned code that visual studio generates for Individual User Accounts.

There's a line in the StartUp.Auth.cs code that looks like this.

app.UseOAuthBearerTokens(OAuthOptions);

With this in place, I can add the [Authorize] attribute to controllers and it works fine.

Incidentally, with angular I was able to add a standard header containing the token in the JavaScript as follows.

$http.defaults.headers.common.Authorization = 'bearer ' + access_token;

Then I added SignalR to the project.
It supports it's own version of the [Authorize] attribute but there is no way to pass custom headers when using SignalR.
It's a limitation on the browser side.
The documentation said you could pass the token as part of the query string.
I added that code on the JavaScript side. My SignalR code now included this.
I passed the token as 'bearer_token'.

this.connection = $.hubConnection("/TestHub", { useDefaultPath: false, qs: "bearer_token=" + token });

So my issue was how to make OWIN recognize the token now it was no longer in the header.
After a number of searches, I ended up adding code that moved the token from the querystring into the header.
For my prototype, I just added a little code above the original line in StartUp.Auth.cs.

So, now it looked like this:

app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()
{
Provider = new OAuthBearerAuthenticationProvider()
{
OnRequestToken = context =>
{
if (context.Request.Path.Value.StartsWith("/TestHub"))
{
string bearerToken = context.Request.Query.Get("bearer_token");
if (bearerToken != null)
{
string[] authorization = new string[] { "bearer " + bearerToken };
context.Request.Headers.Add("Authorization", authorization);
}
}

return Task.FromResult(context);
}
}
});


// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(OAuthOptions);

The code above is rough but this is a prototype so really I just wanted to see if it worked which it did.

**Finally getting to the question:**
Is this the right pattern for integrating bearer token authorization with SignalR and the OWIN pipeline.
I couldn't seem to find much good information on the right way to do this.
Reply

#2
This how I solved it

var authData = localStorageService.get('authorizationData');
var token = authData.token;
$.signalR.ajaxDefaults.headers = { Authorization: "Bearer " + token };

No change on the server side code

Hope it helps someone
Reply

#3
I'll post this for the the people that will have this issue in the future:

There are multiple approaches to this in order to just make it work, but depending on the purpose of the application.

1. The first that I've seen makes `SignalR` work with headers, which would seem very easy to implement:

`$.signalR.ajaxDefaults.headers = { Authorization: "Bearer " + token };`

The huge downside of this is that it forces `SignalR` to use `longPolling`, which you most definitely don't want, since you are using SignalR.

2. The second approach is to pass the `access token` that the client receives when logging in as a `query string`, right before connecting. Then, make a custom `Attribute` that inherits the `AuthorizeAttribute` ([follow this repo - not great in my opinion, but it makes a point][1]).

Another approach with passing the token as `query string` is to [follow this SO answer][2] which creates an `OAuth Provider` and

> retrieves all other values from the token early in the pipeline

Again, this method is not the optimal one since `query strings` are pretty vulnerable:

> query strings tend to be stored in web server logs (or exposed in
> other ways even when using SSL). There is a risk of someone
> intercepting the tokens. You need to select an approach that fits your
> scenario best.

3. The solution I am currently trying to implement (and will come back with updates once it works:D) is [based on this blog post][3] which uses the `OAuth Bearer Token authentication` with `SignalR` by passing the token over a cookie into `SignalR` pipeline.

I believe this is the solution with the fewest compromises, but I will come back with more information once my implementation is complete.

Hope this helps. Best of luck!


UPDATE
I managed to get WebApi token authentication to work with SignalR by storing the token in a cookie, then retrieve it in a provider.

You cah take a [look at this GitHub repo][4] , but I mostly followed the article from above. Explicitly, here's what I did:

I created an `OAuthBearerTokenAuthenticationProvider` class that inherits from `OAuthBearerAuthenticationProvider` and overridden the `RequestToken` method.

Now it looks for the cookie where the `BearerToken` is stored and retrieves its value. Then, it sets the `context.Token` to the value of the cookie.

Then, on the JavaScript part, you have to get the token (by authenticating using the user name and password) and store the token in a cookie.

public class OAuthBearerTokenAuthenticationProvider : OAuthBearerAuthenticationProvider
{
public override Task RequestToken(OAuthRequestTokenContext context)
{
var tokenCookie = context.OwinContext.Request.Cookies["BearerToken"];

if (!String.IsNullOrEmpty(tokenCookie))
context.Token = tokenCookie;

return Task.FromResult<object>(null);
}
}

For a working sample, please take a look at the repo above.

Best of luck!

[1]:

[To see links please register here]

[2]:

[To see links please register here]

[3]:

[To see links please register here]

[4]:

[To see links please register here]

Reply

#4
I use a class like this:

public class OAuthTokenProvider : OAuthBearerAuthenticationProvider
{
private List<Func<IOwinRequest, string>> _locations;
private readonly Regex _bearerRegex = new Regex("((B|b)earer\\s)");
private const string AuthHeader = "Authorization";

/// <summary>
/// By Default the Token will be searched for on the "Authorization" header.
/// <para> pass additional getters that might return a token string</para>
/// </summary>
/// <param name="locations"></param>
public OAuthTokenProvider(params Func<IOwinRequest, string>[] locations)
{
_locations = locations.ToList();
//Header is used by default
_locations.Add(x => x.Headers.Get(AuthHeader));
}

public override Task RequestToken(OAuthRequestTokenContext context)
{
var getter = _locations.FirstOrDefault(x => !String.IsNullOrWhiteSpace(x(context.Request)));
if (getter != null)
{
var tokenStr = getter(context.Request);
context.Token = _bearerRegex.Replace(tokenStr, "").Trim();
}
return Task.FromResult<object>(null);
}
}

Which instead of just passing on the token to the header, parses it and sets it on the context.

Then it could be used in your app configuration like this:

app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions
{
Provider = new OAuthTokenProvider(
req => req.Query.Get("bearer_token"),
req => req.Query.Get("access_token"),
req => req.Query.Get("token"),
req => req.Headers.Get("X-Token"))
});

Then the following styles of requests would have their token read, for use with authentication and/or authorization:

GET

[To see links please register here]

HTTP/1.1
GET

[To see links please register here]

HTTP/1.1
GET

[To see links please register here]

HTTP/1.1

GET

[To see links please register here]

HTTP/1.1
X-Token: 123ABC

GET

[To see links please register here]

HTTP/1.1
Authorization: 123ABC
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through