Skip to content
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

api: adding a gRPC call for revoking refresh tokens. #802

Merged
merged 1 commit into from
Feb 15, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
159 changes: 111 additions & 48 deletions api/api.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 18 additions & 1 deletion api/api.proto
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ message DeleteClientReq {
string id = 1;
}

// DeleteClientResp determines if the.
// DeleteClientResp determines if the client is deleted successfully.
message DeleteClientResp {
bool not_found = 1;
}
Expand Down Expand Up @@ -120,6 +120,19 @@ message ListRefreshResp {
repeated RefreshTokenRef refresh_tokens = 1;
}

// RevokeRefreshReq is a request to revoke the refresh token of the user-client pair.
message RevokeRefreshReq {
// The "sub" claim returned in the ID Token.
string user_id = 1;
string client_id = 2;
}

// RevokeRefreshResp determines if the refresh token is revoked successfully.
message RevokeRefreshResp {
// Set to true is refresh token was not found and token could not be revoked.
bool not_found = 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is never set?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Set this to true when UpdateOfflineSession returns err == storage.ErrNotFound.

}

// Dex represents the dex gRPC service.
service Dex {
// CreateClient creates a client.
Expand All @@ -138,4 +151,8 @@ service Dex {
rpc GetVersion(VersionReq) returns (VersionResp) {};
// ListRefresh lists all the refresh token entries for a particular user.
rpc ListRefresh(ListRefreshReq) returns (ListRefreshResp) {};
// RevokeRefresh revokes the refresh token for the provided user-client pair.
//
// Note that each user-client pair can have only one refresh token at a time.
rpc RevokeRefresh(RevokeRefreshReq) returns (RevokeRefreshResp) {};
}
42 changes: 39 additions & 3 deletions server/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (

// apiVersion increases every time a new call is added to the API. Clients should use this info
// to determine if the server supports specific features.
const apiVersion = 0
const apiVersion = 1

// NewAPI returns a server which implements the gRPC API interface.
func NewAPI(s storage.Storage, logger logrus.FieldLogger) api.DexServer {
Expand Down Expand Up @@ -204,13 +204,13 @@ func (d dexAPI) ListRefresh(ctx context.Context, req *api.ListRefreshReq) (*api.
id := new(internal.IDTokenSubject)
if err := internal.Unmarshal(req.UserId, id); err != nil {
d.logger.Errorf("api: failed to unmarshal ID Token subject: %v", err)
return nil, fmt.Errorf("unmarshal ID Token subject: %v", err)
return nil, err
}

offlineSessions, err := d.s.GetOfflineSessions(id.UserId, id.ConnId)
if err != nil {
d.logger.Errorf("api: failed to list refresh tokens: %v", err)
return nil, fmt.Errorf("list refresh tokens: %v", err)
return nil, err
}

var refreshTokenRefs []*api.RefreshTokenRef
Expand All @@ -228,3 +228,39 @@ func (d dexAPI) ListRefresh(ctx context.Context, req *api.ListRefreshReq) (*api.
RefreshTokens: refreshTokenRefs,
}, nil
}

func (d dexAPI) RevokeRefresh(ctx context.Context, req *api.RevokeRefreshReq) (*api.RevokeRefreshResp, error) {
id := new(internal.IDTokenSubject)
if err := internal.Unmarshal(req.UserId, id); err != nil {
d.logger.Errorf("api: failed to unmarshal ID Token subject: %v", err)
return nil, err
}

var refreshID string
updater := func(old storage.OfflineSessions) (storage.OfflineSessions, error) {
if refreshID = old.Refresh[req.ClientId].ID; refreshID == "" {
return old, fmt.Errorf("user does not have a refresh token for the client = %s", req.ClientId)
}

// Remove entry from Refresh list of the OfflineSession object.
delete(old.Refresh, req.ClientId)

return old, nil
}

if err := d.s.UpdateOfflineSessions(id.UserId, id.ConnId, updater); err != nil {
if err == storage.ErrNotFound {
return &api.RevokeRefreshResp{NotFound: true}, nil
}
d.logger.Errorf("api: failed to update offline session object: %v", err)
return nil, err
}

// Delete the refresh token from the storage
if err := d.s.DeleteRefresh(refreshID); err != nil {
d.logger.Errorf("failed to delete refresh token: %v", err)
return nil, err
}

return &api.RevokeRefreshResp{}, nil
}
Loading