Problem authorization Urb-IT API

Solved!
Posted in General by Niklas Hultgren Thu Oct 29 2015 11:41:01 GMT+0000 (UTC)·8·Viewed 214 times

Hi, I’m trying to fetch opening hours for a store but I’m having problems with the authentication. I build the authentication header as mentioned here: http://developer.urb-it.com/v1.0/docs/create-the-authorization-header Below is what I get in my logfile. Can you see anything wrong? Not OK returned from Urb-It API: Elapsed time [0:058 seconds] [ Unauthorized ] Parameters: [ application/json={ "from": "2015-10-29T11:35:57.5244218Z", "to": "2015-11-05T11:35:57.5244218Z", "closed": false } : Authorization=UWA 31a8ef40-071c-4f7c-bdfa-1258a7ee7105:vcI59FTY6bDoPqTHwMBJeQyjyjUlNK58pc5IEcOl+kw=:ea5f332f-4ee0-4ea6-849e-b38bd55c7096:1446122157,52542 : Accept=application/vnd.urb-it.se+json; version=1 ] Method: [ openinghours (https://stage-retailer-api.urb-it.com/api/openinghours)] Status [ StatusCode: Unauthorized, StatusDescription: {"status":401,"code":"401","message":"Invalid authorization method.","developer_message":"The provided authorization method is not supported. Supported methods are OAuth1a and UWA.","more_info":null} ]
Mihai Borz
Oct 29, 2015
Hi, thank you for your message, According to the logs it looks like parameters(from, to) and the authorization header are not present. The request url should look like: https://stage-retailer-api.urb-it.com/api/openinghours?from=2015-10-15&to=2015-10-17 The authorization header looks fine but you need to set it as http header. Can you also send your request/code example in case it still does’t work for you?
Niklas Hultgren
Oct 29, 2015
Hi, The parameters are set in the request body, not as query strings. The documentation doesn’t specify that they should be sent as querystrings so i assumed that they should go in the body of the request. But this may be the case because the method in question uses GET. When it comes to the authorization header I do explicitly set in in the request header. My log is just specifying the value. It is not a copy of the real request. I also set the Accept header as you can see from above. // Niklas
Niklas Hultgren
Oct 29, 2015
I use RestSharp (C#) for building the request. Below is part of my code. I create a restclient to which I add parameters and the Auth header. Can you see any log from your end if you’re getting my Auth header? var restClient = new RestClient(BaseAddress); if (requestParameters.Body != null) { restRequest.AddBody(requestParameters.Body); //here goes my from and to dates … } AppendAuthHeader(restRequest, requestParameters); AppendAcceptHeader(restRequest); var response = restClient.Execute(restRequest); —– Other methods —- virtual protected void AppendAuthHeader(RestRequest request, Request currentRequest) { var authHeader = BuildAuthHeader(currentRequest); if (!string.IsNullOrWhiteSpace(authHeader)) { request.AddParameter("Authorization", authHeader, ParameterType.HttpHeader); // request.AddHeader("Authorization", authHeader); } else { Logger.Warning("Authorization header is missing!"); } } virtual protected void AppendAcceptHeader(RestRequest request) { request.AddHeader("Accept", string.Format("application/vnd.urb-it.se+json; version={0}", Settings.Instance.UrbItCurrentApiVersion)); } private string BuildAuthHeader(Request currentRequest) { try { var contentAsJson = GetBodyContentAsJson(currentRequest.Body); var content = Encoding.UTF8.GetBytes(contentAsJson); var requestContentHash = MD5.Create().ComputeHash(content); var nonce = Guid.NewGuid().ToString(); var requestTimeStamp = TimeStamp; var url = GetApiUrl(currentRequest); var msgToSisgn = String.Format("{0}{1}{2}{3}{4}{5}", Settings.Instance.UrbItStoreKey, currentRequest.Method.ToMethodString(), url, requestTimeStamp, nonce, Convert.ToBase64String(requestContentHash)); var secretKeyByteArray = Convert.FromBase64String(Settings.Instance.UrbItSharedSecretKey); using (var hmac = new HMACSHA256(secretKeyByteArray)) { byte[] signatureBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(msgToSisgn)); var requestSignatureBase64String = Convert.ToBase64String(signatureBytes); return String.Format("UWA {0}:{1}:{2}:{3}", Settings.Instance.UrbItStoreKey, requestSignatureBase64String, nonce, requestTimeStamp); } } catch (Exception ex) { Logger.Error("An error occured when trying to build the Authorization header before calling Urb-It", ex); } return string.Empty; } private string GetBodyContentAsJson(object body) { if (body == null) return string.Empty; try { return JsonSerializer.Serialize(body); } catch (Exception ex) { Logger.Error("An error occured when trying to serialize the current object to json", ex); } return string.Empty; } private string GetApiUrl(Request currentRequest) { Uri result; return Uri.TryCreate(new Uri(BaseAddress), currentRequest.Segment, out result) ? result.ToString() : string.Empty; } private static double TimeStamp { get { return DateTime.Now.Subtract(new DateTime(1970, 01, 01, 00, 00, 00)).TotalSeconds; } }
Mihai Borz
Oct 29, 2015
Hi, the url that you sign in the BuildAuthHeader method needs to contain the query string parameters. Since the body is empty you do not need to include it in the signature, “`C# private string BuildAuthHeader(Request currentRequest) { try { var contentAsJson = GetBodyContentAsJson(currentRequest.Body); var content = Encoding.UTF8.GetBytes(contentAsJson); var requestContentHash = MD5.Create().ComputeHash(content); var nonce = Guid.NewGuid().ToString(); var requestTimeStamp = TimeStamp; var url = GetApiUrl(currentRequest); // here we need the url with query string. var contentToSign = currentRequest.Method == Method.GET ? String.Empty : Convert.ToBase64String(requestContentHash); var msgToSisgn = String.Format("{0}{1}{2}{3}{4}{5}", Settings.Instance.UrbItStoreKey, currentRequest.Method.ToMethodString(), url, requestTimeStamp, nonce, contentToSign); var secretKeyByteArray = Convert.FromBase64String(Settings.Instance.UrbItSharedSecretKey); using (var hmac = new HMACSHA256(secretKeyByteArray)) { byte[] signatureBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(msgToSisgn)); var requestSignatureBase64String = Convert.ToBase64String(signatureBytes); return String.Format("UWA {0}:{1}:{2}:{3}", Settings.Instance.UrbItStoreKey, requestSignatureBase64String, nonce, requestTimeStamp); } } catch (Exception ex) { //Logger.Error("An error occured when trying to build the Authorization header before calling Urb-It", ex); } return string.Empty; } “`
Mihai Borz
Oct 29, 2015
Can you test again and sent me the time when you sent the request? There are too many requests now and I cannot figure out which one is yours,
Niklas Hultgren
Oct 29, 2015
I’ve done some refactoring of the code and taking your suggestions into count. But still I get the Unauthorized response. This time I’ve implemented a IAuthenticator in the attempt to set the Authorization header. Like this: public class UrbitWebAuthorization : IAuthenticator { private readonly string _token; public UrbitWebAuthorization(string token) { _token = token; } public void Authenticate(IRestClient client, IRestRequest request) { request.AddHeader("Authorization", _token); } } var restClient = new RestClient(BaseAddress) { Authenticator = new UrbitWebAuthorization(authToken) }; So it must be set, I belive. My last request was sent around 19:45 (7:45:09 PM). Can you see my request and if the header is sent? If you want I could mail you my source code. // Niklas
Niklas Hultgren
Oct 30, 2015
Hi again, This morning I did a little "investigation" and build my own API for checking the actual headers sent from our application. This is the result: {Connection: Keep-Alive Accept: application/vnd.urb-it.se+json; version=1 Accept-Encoding: gzip, deflate Authorization: UWA 31a8ef40-071c-4f7c-bdfa-1258a7ee7105:auNp3h0vLnueWGOnSzCZAp0a2pwbYFcV+xzb2OMKh5Y=:54c0abe0-7b5c-4b4f-abd5-c256cbb7cde5:1446187343,64793 Host: 78.71.216.9 User-Agent: RestSharp/105.2.3.0 } Looks ok, dosen’t it? But still I get that 401 in the face! 😉 Please check your logs and verify the headers on your end. Thanx! // Niklas

Tommy Hägvall marked this as solved
Markdown is allowed