final AuthenticationTokenSupplier tokenSupplier = new AuthenticationTokenSupplier(teamId, keyId, signingKey);
/** * Returns the most recently-generated authentication token created by this provider. Generates a new token with the * given "issued at" timestamp if the most recent token has been invalidated (or if no token has ever been generated * by this provider). * * @param issuedAt the "issued at" time for newly-generated tokens; ignored if an existing token is available * * @return a signed, base64url-encoded JWT authentication token * * @throws SignatureException if the authentication token could not be signed for any reason */ protected String getToken(final Date issuedAt) throws SignatureException { if (this.token == null) { final String header = gson.toJson(new AuthenticationTokenHeader(this.keyId)); final String claims = gson.toJson(new AuthenticationTokenClaims(this.issuer, issuedAt)); final StringBuilder payloadBuilder = new StringBuilder(); payloadBuilder.append(base64UrlEncodeWithoutPadding(header.getBytes(StandardCharsets.US_ASCII))); payloadBuilder.append('.'); payloadBuilder.append(base64UrlEncodeWithoutPadding(claims.getBytes(StandardCharsets.US_ASCII))); final byte[] signatureBytes; { this.signature.update(payloadBuilder.toString().getBytes(StandardCharsets.US_ASCII)); signatureBytes = this.signature.sign(); } payloadBuilder.append('.'); payloadBuilder.append(base64UrlEncodeWithoutPadding(signatureBytes)); this.token = payloadBuilder.toString(); } return this.token; }
/** * Returns the most recently-generated authentication token created by this provider. Generates a new token if * the most recent token has been invalidated (or if no token has ever been generated by this provider). * * @return a signed, base64url-encoded JWT authentication token * * @throws SignatureException if the authentication token could not be signed for any reason * * @see AuthenticationTokenSupplier#invalidateToken(String) */ public String getToken() throws SignatureException { return this.getToken(new Date()); }
@Override public int onDataRead(final ChannelHandlerContext context, final int streamId, final ByteBuf data, final int padding, final boolean endOfStream) throws Http2Exception { log.trace("Received data from APNs gateway on stream {}: {}", streamId, data.toString(StandardCharsets.UTF_8)); final int bytesProcessed = data.readableBytes() + padding; if (endOfStream) { final Http2Headers headers = ApnsClientHandler.this.headersByStreamId.remove(streamId); final String authenticationToken = ApnsClientHandler.this.authenticationTokensByStreamId.remove(streamId); final ApnsPushNotification pushNotification = ApnsClientHandler.this.pushNotificationsByStreamId.remove(streamId); final HttpResponseStatus status = HttpResponseStatus.parseLine(headers.status()); final String responseBody = data.toString(StandardCharsets.UTF_8); if (HttpResponseStatus.INTERNAL_SERVER_ERROR.equals(status)) { ApnsClientHandler.this.apnsClient.handleServerError(pushNotification, responseBody); } else { final ErrorResponse errorResponse = gson.fromJson(responseBody, ErrorResponse.class); if (ApnsClient.EXPIRED_AUTH_TOKEN_REASON.equals(errorResponse.getReason())) { try { ApnsClientHandler.this.apnsClient.getAuthenticationTokenSupplierForTopic(pushNotification.getTopic()).invalidateToken(authenticationToken); } catch (final NoKeyForTopicException e) { // This should only happen if somebody de-registered the topic after a notification was sent log.warn("Authentication token expired, but no key registered for topic {}", pushNotification.getTopic()); } } ApnsClientHandler.this.apnsClient.handlePushNotificationResponse( new SimplePushNotificationResponse<>(pushNotification, HttpResponseStatus.OK.equals(status), errorResponse.getReason(), errorResponse.getTimestamp())); } } else { log.error("Gateway sent a DATA frame that was not the end of a stream."); } return bytesProcessed; }
authenticationToken = this.apnsClient.getAuthenticationTokenSupplierForTopic(pushNotification.getTopic()).getToken(); headers.add(APNS_AUTHORIZATION_HEADER, "bearer " + authenticationToken); } else {