Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OAuth 2 bearer Authorization header

With an update to the client's API the HTTPBasicAuthication method has been replace with a OAuth2 Bearer Authorization header.

With the old API I would do the following:

NSURLCredential *credential = [NSURLCredential credentialWithUser:self.account.username 
                                                         password:self.account.token 
                                                      persistence:NSURLCredentialPersistenceForSession];

NSURLProtectionSpace *space = [[NSURLProtectionSpace alloc] initWithHost:kAPIHost
                                                                    port:443
                                                                protocol:NSURLProtectionSpaceHTTPS
                                                                   realm:@"my-api"
                                                    authenticationMethod:NSURLAuthenticationMethodHTTPBasic];

But this will not work with the Bearer header.

Now normally I would just add the header my self by adding it like so:

NSString *authorization = [NSString stringWithFormat:@"Bearer %@",self.account.token];
[urlRequest setValue:authorization forHTTPHeaderField:@"Authorization"];

But the problem with this solutions is that the API redirect most of the calls to other URLs, this has to do with security. After the NSURLRequest gets redirected the Authorization header is removed from the request and since I'm unable to add the Bearer method to the NSURLCredentialStorage it can't authenticate any more after being redirected.

What would be a good solutions? I can only think to catch the redirect and modify the NSURLRequest so it does include the Bearer header. But how?

like image 838
rckoenes Avatar asked Aug 23 '12 12:08

rckoenes


People also ask

How do I pass Authorization bearer in header?

To send a request with the Bearer Token authorization header, you need to make an HTTP request and provide your Bearer Token with the "Authorization: Bearer {token}" header. A Bearer Token is a cryptic string typically generated by the server in response to a login request.

What is bearer Authorization header?

The bearer token is a cryptic string, usually generated by the server in response to a login request. The client must send this token in the Authorization header when making requests to protected resources: Authorization: Bearer.

Is bearer required in Authorization header?

Long before bearer authorization, this header was used for Basic authentication. For interoperability, the use of these headers is governed by W3C norms, so even if you're reading and writing the header, you should follow them. Bearer distinguishes the type of Authorization you're using, so it's important.

What is OAuth header?

OAuth 1.0a uses the Authorization header as a way to authenticate the client to the OAuth Provider itself. In OAuth 2.0, this header isn't used for authentication with the OAuth Provider. Instead, OAuth 2.0 uses query parameters in the payload.


3 Answers

Well after much research I found out that I will just have to replace the NSURLRequest when a call is redirected.

Not as nice as I would like it to be, but is does work.

I used AFNetworking and added the redirect block, then check wether the Authorization header is still set if not I create a new NSMutableURLRequest and set all the properties to match the old request (I know I could have just created a mutable copy):

[requestOperation setRedirectResponseBlock:^NSURLRequest *(NSURLConnection *connection, NSURLRequest *request, NSURLResponse *redirectResponse) {

    if ([request.allHTTPHeaderFields objectForKey:@"Authorization"] != nil) {
        return request;
    }

    NSMutableURLRequest *urlRequest = [[NSMutableURLRequest alloc] initWithURL:request.URL cachePolicy:request.cachePolicy timeoutInterval:request.timeoutInterval];
    NSString *authValue = [NSString stringWithFormat:@"Bearer %@", self.account.token];
    [urlRequest setValue:authValue forHTTPHeaderField:@"Authorization"];

    return  urlRequest;

}];
like image 111
rckoenes Avatar answered Oct 14 '22 04:10

rckoenes


I'm using AFNetworking Library

Find AFHttpClient.m and you have a method

- (void)setAuthorizationHeaderWithToken:(NSString *)token {
    [self setDefaultHeader:@"Authorization" value:[NSString stringWithFormat:@"Token token=\"%@\"", token]];
}

replace this method with the following or if you need it for back compatibility keep it an add with a different name and use that name

- (void)setAuthorizationHeaderWithToken:(NSString *)token {
    [self setDefaultHeader:@"Authorization" value:[NSString stringWithFormat:@"Bearer %@", token]];
}

then make the request with oauth access token. (Following is a GET method service)

    NSURL *url = [EFServiceUrlProvider getServiceUrlForMethod:methodName];
    AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
    [httpClient setAuthorizationHeaderWithToken:@"add your access token here"];

    [httpClient getPath:@"" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSString *response = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        //
    }];

Updated


Use Oauth2 Client on AFNetworking written by matt

https://github.com/AFNetworking/AFOAuth2Client

like image 43
MadNik Avatar answered Oct 14 '22 03:10

MadNik


If you happen to be having this issue with Django rest framework and the routers the problem might be related to the trailing slash being clipped by the NSUrlRequest. if the trailing slash is clipped then django will have to redirect your request, to avoid this you can use Trailing_slash = True like this

router = routers.DefaultRouter(trailing_slash=False)

That way not your authorization header nor your parameters will get lost.

Hope this saves somebody some time.

like image 37
Andrespch Avatar answered Oct 14 '22 02:10

Andrespch