Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SignatureCalculator.constructAuthHeader()] Should nonce be URL encoded? #57

Open
boriguen opened this issue Feb 8, 2019 · 5 comments

Comments

@boriguen
Copy link

boriguen commented Feb 8, 2019

Hi,

I have observed a pattern regarding success or failure of the authorization request depending on whether the nonce was URL encoded while containing special characters. Removing the urlEncode() call seems to make all requests succeed.

Here are a couple examples to illustrate:

Successes

headerValue=OAuth oauth_consumer_key="***", oauth_signature_method="HMAC-SHA256", oauth_signature="wrlkVTMc%2F68A1asrCNlWNRPYzbpsQCrtrmrYYeBG7kk%3D", oauth_timestamp="1549652196", oauth_nonce="f1lpHr", oauth_version="1.0"

headerValue=OAuth oauth_consumer_key="***", oauth_signature_method="HMAC-SHA256", oauth_signature="Sl%2FECnifUqQQQJSkjrzhNxuZYfJGnepqXBAxxC4TwcI%3D", oauth_timestamp="1549652201", oauth_nonce="lrCx33", oauth_version="1.0"

headerValue=OAuth oauth_consumer_key="***", oauth_signature_method="HMAC-SHA256", oauth_signature="v%2Bz20gofBYj7UXXE1rAKjXLGZFkxsQWPiDwBCWCdkaI%3D", oauth_timestamp="1549653242", oauth_nonce="G8mmeS", oauth_version="1.0"

Failures

headerValue=OAuth oauth_consumer_key="***", oauth_signature_method="HMAC-SHA256", oauth_signature="4ia8%2Fsm1luNP2hXVxzl34%2BiGOkOQSkwmFC1GlQgW75w%3D", oauth_timestamp="1549653142", oauth_nonce="vH2Z%2FH", oauth_version="1.0"

headerValue=OAuth oauth_consumer_key="***", oauth_signature_method="HMAC-SHA256", oauth_signature="01j%2B85U77ehTBcDxd0OUTpfekIXjtfmzQX8YCvp12wU%3D", oauth_timestamp="1549653244", oauth_nonce="V%2FK6kl", oauth_version="1.0"

headerValue=OAuth oauth_consumer_key="***", oauth_signature_method="HMAC-SHA256", oauth_signature="UwULcKgLyzD0VpDZIChQE8R5kVycTNz0bWQI%2Fdn71iU%3D", oauth_timestamp="1549653304", oauth_nonce="A%2Bp5oH", oauth_version="1.0"

I haven't investigated too deep into the issue but removing the urlEncode(nonce) and only appending nonce as-is seems to lead a 100% success rate, even with oauth_nonce="7g+/D1" or oauth_nonce="Zs/a9h".

Please feel free to check the hypothesis a bit further.

Thanks,

Boris

@kenmccracken
Copy link
Collaborator

Hi Boris,

Thanks for the issue report. I did some investigation into our use of Base64 currently in the library. The alphabet used in java.util.Base64 for url-safe seems to be

      /**
        * It's the lookup table for "URL and Filename safe Base64" as specified
        * in Table 2 of the RFC 4648, with the '+' and '/' changed to '-' and
        * '_'. This table is used when BASE64_URL is specified.
        */
       private static final char[] toBase64URL = {
           'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
           'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
           'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
           'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
           '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'
       };

and so I don't think we see this particular problem when using this library.

If you catch your exceptions, could you call

((AccessTokenException) exc).getErrorResponse().toString()

on them to print to a log, and add to this issue report? This will include more detailed error information, to help with investigation into this issue.

Thanks,
-Ken

@boriguen
Copy link
Author

Hi Ken,

Apologies for the delay as this slipped through. I believe your analysis makes sense and this only comes from Base 64 switch. I will work on reproducing the issue and share the exception content.

Thanks,

Boris

@boriguen
Copy link
Author

Here is the log:

com.here.account.oauth2.AccessTokenException: HTTP status code 401, body ErrorResponse [error=invalid_client, errorDescription=errorCode: '401300'. Signature mismatch. Authorization signature or client credential is wrong., httpStatus=401, errorId=ERROR-67d23d03-5415-4f8f-8c3b-28799864a82e, errorCode=401300, message=Signature mismatch. Authorization signature or client credential is wrong.]

	at com.here.account.oauth2.HereAccount$TokenEndpointImpl.lambda$requestTokenHttp$0(HereAccount.java:408)
	at com.here.account.client.Client.sendMessage(Client.java:245)
	at com.here.account.oauth2.HereAccount$TokenEndpointImpl.requestTokenHttp(HereAccount.java:406)
	at com.here.account.oauth2.HereAccount$TokenEndpointImpl.requestToken(HereAccount.java:391)
	at com.here.account.oauth2.HereAccessTokenProvider.getAccessTokenResponse(HereAccessTokenProvider.java:256)
	at com.here.account.oauth2.HereAccessTokenProvider.getAccessToken(HereAccessTokenProvider.java:249)
	at com.here.account.android.HereAccountTokenProvider.getToken(HereAccountTokenProvider.java:75)

This said, I think this issue can be closed as it doesn't happen in this official library, only in my tweaked code.

@kenmccracken
Copy link
Collaborator

Thank you for the details. I have filed a ticket internally for the server team to look into. If this is all that's blocking usage of the library from Android, I think this might be worth fixing anyway. From what I can tell the OAuth 1.0 spec RFC 5849 is ambiguous about characters used for oauth_nonce, so if we fall back to RFC 2616, '%' should be supported.

@kenmccracken
Copy link
Collaborator

Hi @boriguen , I think from reading the OAuth specs https://tools.ietf.org/html/rfc5849#section-3.5.1 , it says "1. Parameter names and values are encoded per Parameter Encoding (Section 3.6)." So if your nonce includes '+' and/or '/', the client must use it plaintext in the signature calculation, but must URL-encode it when sending it in the Authorization header.

Have you tried replacing '+' and '/' in your nonce values, with '-' and '_', respectively, in your replacement for

        String nonce = Base64.getUrlEncoder().withoutPadding().encodeToString(bytes).substring(0, NONCE_LENGTH);

? That would effectively provide you with a URL-safe Base64-encoder. Note knowing how you overrode the lack of java.util.Base64 class in your environment, I'm not sure how you handled that. If you could provide more details on your work-around, that might help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants