goexpoexpo-notifications

Got "x.509 certificate signed by unknown authority" when the server tried to send Expo notifications


I got "x.509 certificate signed by unknown authority" error message when I tried to send notifications to the Expo Push Notification server.

My server written in Golang stores expo push tokens. Then, it loads those tokens and build expo.PushMessage list and push them using PublishMultiple function.

I have two servers, one is for test and the other is for the production. It works well in the test server. I got push notification on my testing phone. So, I updated my production server, then the production server produces x.509 certificate signed by unknown authority message.

First, I suspect that my expo push token had been corrupted, but the push token works well when I used Expo push notifications tool.

I am not sure where to look for a solution. Can anyone help me? I'll revise the question if you want to know about my server code or settings. At this moment, I'm not sure which part of code or settings should be provided to find a solution.

The following codes are around the only place that the error can occur.

import (
    expo "github.com/oliveroneill/exponent-server-sdk-golang/sdk"
    "github.com/pkg/errors"
)

type Client struct {
    PushClient *expo.PushClient
}

func NewClient() *Client {
    client := expo.NewPushClient(nil)

    return &Client{PushClient: client}
}

func (c *Client) PushNotifications(deviceKeys []string, title string, body string) (error, map[string]string) {
    messages := make([]expo.PushMessage, 0)
    for _, deviceKey := range deviceKeys {
        pushToken, err := expo.NewExponentPushToken(deviceKey)
        if err != nil {
            continue
        }

        messages = append(messages, expo.PushMessage{
            To:        pushToken,
            Body:      body,
            Data:      nil,
            Sound:     "default",
            Title:     title,
            Priority:  expo.DefaultPriority,
            ChannelID: "default",
        })
    }

    // This is only place the error can occur
    // PublishMultiple function is a part of the Expo SDK
    responses, err := c.PushClient.PublishMultiple(messages)
    if err != nil {
        return errors.WithStack(err), nil
    }

    sentErrors := make(map[string]string)
    for index, response := range responses {
        err := response.ValidateResponse()
        if err != nil && index >= len(deviceKeys) {
            sentErrors[deviceKeys[index]] = err.Error()
        }
    }

    return nil, sentErrors
}

A dockerfile to build my production server:

FROM golang:1.13-alpine as builder

WORKDIR /usr/src/app
ARG app
COPY . .

RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -mod vendor -a -ldflags '-s' -o main ./apps/$app

FROM scratch

COPY --from=builder /usr/src/app/main /app/main

WORKDIR /app
CMD ["./main"]

Solution

  • golang:*-alpine images are intentionally minimal and do not have a system certificate pool.

    The simplest solution is to add it yourself when building your docker image by adding:

    RUN apk add --no-cache ca-certificates