-
Notifications
You must be signed in to change notification settings - Fork 1.2k
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to handle authorization in subscriptions? #1297
Comments
|
I got it till the part of the I do not know how to access the |
Here is a simple example: // appContext.go
const (
AppContextKey = "appContext"
)
type AppContext struct {
Token string
UserId string
Cancel context.CancelFunc
}
func ForAppContext(ctx context.Context) *AppContext {
c, _ := ctx.Value(AppContextKey).(*AppContext)
return c
} // init.go
h := handler.New(generated.NewExecutableSchema(generated.Config{Resolvers: &resolver.Resolver{}}))
// ...
h.AddTransport(transport.Websocket{
Upgrader: websocket.Upgrader{
HandshakeTimeout: time.Minute,
CheckOrigin: func(r *http.Request) bool {
// we are already checking for CORS
return true
},
EnableCompression: true,
},
InitFunc: func(ctx context.Context, initPayload transport.InitPayload) (context.Context, error) {
if token := initPayload.Authorization(); middleware.CouldBetoken(token) {
if intro, err := oauth2.IntrospectToken(token[7:], false); err == nil && intro != nil && oauth2.IsIntrospectionValid(intro) {
nctx, cancel := context.WithCancel(ctx)
return context.WithValue(nctx, middleware.AppContextKey, &middleware.AppContext{
Token: token[7:],
UserId: intro.Sub,
Cancel: cancel,
}), nil
}
}
return ctx, errors.New("AUTHORIZATION_REQUIRED")
},
KeepAlivePingInterval: viper.GetDuration(config.WebsocketKeepAliveKey),
})
// ... // resolvers.go
func (r *subscriptionResolver) Notification(ctx context.Context, id string) (<-chan *model.Notification, error) {
appContext := middleware.ForAppContext(ctx)
if !oauth2.IsValid(appContext.Token) {
appContext.Cancel() // stop sending keep alive
return nil, nil
}
// ...
} I would love to have the ability to close the websocket entirely instead of hoping the client disconnects. In a way like this: // resolvers.go
func (r *subscriptionResolver) Notification(ctx context.Context, id string) (<-chan *model.Notification, error) {
appContext := middleware.ForAppContext(ctx)
if !oauth2.IsValid(appContext.Token) {
conn := middleware.ForWsConnection(ctx)
conn.Close(websocket.CloseNormalClosure, "unauthorized")
return nil, nil
}
// ...
} |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
Hello, I also have issues getting the authentication working with subscriptions. It works great for queries and mutations as it gets the token from the request header and stores it into the context of the resolver. Unfortunately, it doesn't work for subscriptions. Does anyone know why or how to get it working using the previously mentioned package? Thanks |
You have to check authentication on init and store all you need in returned context. Then you can access this data and recheck authentication and authorization in your subscription resolver. This example should be very similar when using jwt. |
@razorness I see. That actually makes sense after reading a bit more about the websocket protocol. Thank you :) |
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
How Can I handle authorization in subscriptions? The current recipe is outdated. I managed to set authorization for queries and mutations. Can somebody point me into the right direction?
The text was updated successfully, but these errors were encountered: