WrapStreamingHandler implements the ConnectRPC interceptor interface for streaming handlers.
(next connect.StreamingHandlerFunc)
| 113 | |
| 114 | // WrapStreamingHandler implements the ConnectRPC interceptor interface for streaming handlers. |
| 115 | func (in *APIAuthInterceptor) WrapStreamingHandler(next connect.StreamingHandlerFunc) connect.StreamingHandlerFunc { |
| 116 | return func(ctx context.Context, conn connect.StreamingHandlerConn) error { |
| 117 | accessTokenStr, err := GetTokenFromHeaders(conn.RequestHeader()) |
| 118 | if err != nil { |
| 119 | return connect.NewError(connect.CodeUnauthenticated, err) |
| 120 | } |
| 121 | |
| 122 | authContext, err := getAuthContext(conn.Spec().Procedure) |
| 123 | if err != nil { |
| 124 | return err |
| 125 | } |
| 126 | ctx = context.WithValue(ctx, common.AuthContextKey, authContext) |
| 127 | |
| 128 | user, claims, err := in.authenticate(ctx, accessTokenStr) |
| 129 | if err != nil { |
| 130 | if IsAuthenticationSkipped(conn.Spec().Procedure, authContext) { |
| 131 | return next(ctx, conn) |
| 132 | } |
| 133 | return connect.NewError(connect.CodeUnauthenticated, err) |
| 134 | } |
| 135 | |
| 136 | in.profile.LastActiveTS.Store(time.Now().Unix()) |
| 137 | ctx = context.WithValue(ctx, common.UserContextKey, user) |
| 138 | ctx = context.WithValue(ctx, common.WorkspaceIDContextKey, claims.WorkspaceID) |
| 139 | |
| 140 | var tokenExpiry time.Time |
| 141 | if claims.ExpiresAt != nil { |
| 142 | tokenExpiry = claims.ExpiresAt.Time |
| 143 | } |
| 144 | |
| 145 | return next(ctx, &authStreamingConn{ |
| 146 | StreamingHandlerConn: conn, |
| 147 | tokenExpiry: tokenExpiry, |
| 148 | }) |
| 149 | } |
| 150 | } |
| 151 | |
| 152 | // authStreamingConn wraps a streaming connection to check token expiry on every received message. |
| 153 | type authStreamingConn struct { |
nothing calls this directly
no test coverage detected