0

I'm getting the following error when making a push notification request to APNS: &{403 Forbidden 403 HTTP/2.0 2 0 map[Apns-Id:[7BF53274-A04B-7C1B-8312-DB01DA48A519]] {0xc0000c88c0} -1 [] false false map[] 0xc000132000 0xc0000ba370}

I suspect my code to generate an authentication header is not correct

Here's the relevant code:

func generateAuthenticationHeader() string {
    b, _ := json.Marshal(Header{ ALG: "ES256", KID: authKeyId })
    header := b64.StdEncoding.EncodeToString(b)

    b, _ = json.Marshal(Claims{ ISS: teamId, IAT: time.Now().String() })
    claims := b64.StdEncoding.EncodeToString(b)

    pkey := getPrivateKey()

    indata := fmt.Sprintf("%s.%s", header, claims)
    h := sha256.New()
    h.Write([]byte(indata))
    digest := h.Sum(nil)

    r, s, err := ecdsa.Sign(rand.Reader, pkey, digest)
    if err != nil {
        log.Fatal(err)
    }

    signature := r.Bytes()
    signature = append(signature, s.Bytes()...)

    signed := b64.StdEncoding.EncodeToString(signature)

    return fmt.Sprintf("%s.%s.%s", header, claims, signed)
}

func getPrivateKey() *ecdsa.PrivateKey {
    r, _ := ioutil.ReadFile(authKeyPath)
    block, _ := pem.Decode(r)

    key, err := x509.ParsePKCS8PrivateKey(block.Bytes)
    if err != nil {
        log.Fatal(err)
    }
    pkey := key.(*ecdsa.PrivateKey)

    return pkey
}
  • 1
    1) Have you tried this with one of the available jwt packages? 2) Are you sure you have all the claims required? – Burak Serdar Oct 09 '19 at 16:31
  • @bserdar I haven't tried any JWT packages, and yes, the claims are all there. –  Oct 09 '19 at 16:49
  • 1
    One way you can see if your jwt is broken or not is to try it on jwt.io, see if it can decode it. How are you sending the jwt? Is it bearer auth? – Burak Serdar Oct 09 '19 at 16:57
  • @bserdar I've fixed it; I had to change the IAT claim type from string to int64, and use time.Now().Unix() instead of String(). I've just now read Apple's documentation, probably should've done that before. Thanks anyway :) –  Oct 09 '19 at 17:01

1 Answers1

0

The problem was incorrect IAT claim type. Instead of string it should be int64 and time should be in seconds. Calling String() on time.Now() returns a different format from what Apple expects the IAT claim to be, per their documentation: https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/establishing_a_token-based_connection_to_apns.