func (h *handlerManager) validateTTNAuthAppContext(ctx context.Context, appID string) (context.Context, *claims.Claims, error) {
	md, err := api.MetadataFromContext(ctx)
	if err != nil {
		return ctx, nil, err
	}
	// If token is empty, try to get the access key and convert it into a token
	token, err := api.TokenFromMetadata(md)
	if err != nil || token == "" {
		key, err := api.KeyFromMetadata(md)
		if err != nil {
			return ctx, nil, errors.NewErrInvalidArgument("Metadata", "neither token nor key present")
		}
		token, err := h.handler.Component.ExchangeAppKeyForToken(appID, key)
		if err != nil {
			return ctx, nil, err
		}
		md = metadata.Join(md, metadata.Pairs("token", token))
		ctx = metadata.NewContext(ctx, md)
	}
	claims, err := h.handler.Component.ValidateTTNAuthContext(ctx)
	if err != nil {
		return ctx, nil, err
	}
	if h.clientRate.Limit(claims.Subject) {
		return ctx, claims, grpc.Errorf(codes.ResourceExhausted, "Rate limit for client reached")
	}
	if h.applicationRate.Limit(appID) {
		return ctx, claims, grpc.Errorf(codes.ResourceExhausted, "Rate limit for application reached")
	}
	return ctx, claims, nil
}
Exemple #2
0
func (r *routerRPC) gatewayFromMetadata(md metadata.MD) (gtw *gateway.Gateway, err error) {
	gatewayID, err := api.IDFromMetadata(md)
	if err != nil {
		return nil, err
	}

	token, _ := api.TokenFromMetadata(md)

	if !viper.GetBool("router.skip-verify-gateway-token") {
		if token == "" {
			return nil, errors.NewErrPermissionDenied("No gateway token supplied")
		}
		if r.router.TokenKeyProvider == nil {
			return nil, errors.NewErrInternal("No token provider configured")
		}
		claims, err := claims.FromToken(r.router.TokenKeyProvider, token)
		if err != nil {
			return nil, errors.NewErrPermissionDenied(fmt.Sprintf("Gateway token invalid: %s", err.Error()))
		}
		if claims.Type != "gateway" || claims.Subject != gatewayID {
			return nil, errors.NewErrPermissionDenied("Gateway token not consistent")
		}
	}

	gtw = r.router.getGateway(gatewayID)
	gtw.SetToken(token)

	return gtw, nil
}