gauntface / web-push-go

Apache License 2.0
99 stars 14 forks source link

400 Unauthorized Registration with VAPID #21

Open gperrudin opened 7 years ago

gperrudin commented 7 years ago

I'm trying to use the package for web push with vapid (the vapid branch). I always get a 400 status code : UnauthorizedRegistration.

Is there anyone who succeed in using it ?

Thanks in advance.

akyoto commented 7 years ago

I'm having the same issue with VAPID and don't know what I'm doing wrong (it's always "UnauthorizedRegistration").

Maybe there's a problem with the string to []byte conversion.

Edit: I went with another lib which had a minor bug and fixed it in my fork: https://github.com/blitzprog/webpush-go

ali-at-perchwell commented 7 years ago

thank you @blitzprog I was having the same issue and your fork fixed it

anaskhan96 commented 7 years ago

@blitzprog If I may ask, how did you encounter the bug? I use the same library and it works well for me so far. The auth and p256dh keys generated are base64url encoded, so using base64.RawURLEncoding (more like base64.URLEncoding sounds the correct usage since the keys are padded) to decode them sounds legit. Is there a reason you changed it to base64.StdEncoding?

akyoto commented 7 years ago

I'm using Chrome 59 here and RawURLEncoding doesn't work, so I changed the encoding and sent a PR to the original author with this simple change.

Now it's working in both Chrome and Firefox.

The client-side encoding is done via these functions:

// For application server key
function urlBase64ToUint8Array(base64String) {
    const padding = "=".repeat((4 - base64String.length % 4) % 4)
    const base64 = (base64String + padding)
    .replace(/\-/g, "+")
    .replace(/_/g, "/")

    const rawData = window.atob(base64)
    const outputArray = new Uint8Array(rawData.length)

    for(let i = 0; i < rawData.length; ++i) {
        outputArray[i] = rawData.charCodeAt(i)
    }

    return outputArray
}
// For the subscription itself
let rawKey = subscription.getKey("p256dh")
let key = rawKey ? btoa(String.fromCharCode.apply(null, new Uint8Array(rawKey))) : ""

let rawSecret = subscription.getKey("auth")
let secret = rawSecret ? btoa(String.fromCharCode.apply(null, new Uint8Array(rawSecret))) : ""
anaskhan96 commented 7 years ago

Alright it makes sense now that you're using subscription.getKey() and converting the array buffer to a base64 encoded string. In my case, I am using the subscription.toJSON() method (for obtaining the endpoint and the keys in a JSON format), and surprisingly, it returns the keys base64url encoded by default, instead of base64.

I think there should be checks provided in the package to see which particular encoding has been used for the keys.

anaskhan96 commented 7 years ago

So while your fork may fix errors for some people, it might throw new ones for others, just because the encoding from the client side is different.

akyoto commented 7 years ago

I see, then it all makes sense now. It depends on the client-side implementation for key retrieval.