1
21
22 package oauth2
23
24 import (
25 "fmt"
26 "testing"
27
28 "github.com/golang/mock/gomock"
29 "github.com/stretchr/testify/require"
30
31 "github.com/ory/fosite"
32 "github.com/ory/fosite/internal"
33 )
34
35 func TestRevokeToken(t *testing.T) {
36 ctrl := gomock.NewController(t)
37 store := internal.NewMockTokenRevocationStorage(ctrl)
38 atStrat := internal.NewMockAccessTokenStrategy(ctrl)
39 rtStrat := internal.NewMockRefreshTokenStrategy(ctrl)
40 ar := internal.NewMockAccessRequester(ctrl)
41 defer ctrl.Finish()
42
43 h := TokenRevocationHandler{
44 TokenRevocationStorage: store,
45 RefreshTokenStrategy: rtStrat,
46 AccessTokenStrategy: atStrat,
47 }
48
49 var token string
50 var tokenType fosite.TokenType
51
52 for k, c := range []struct {
53 description string
54 mock func()
55 expectErr error
56 client fosite.Client
57 }{
58 {
59 description: "should fail - token was issued to another client",
60 expectErr: fosite.ErrUnauthorizedClient,
61 client: &fosite.DefaultClient{ID: "bar"},
62 mock: func() {
63 token = "foo"
64 tokenType = fosite.RefreshToken
65 rtStrat.EXPECT().RefreshTokenSignature(token)
66 store.EXPECT().GetRefreshTokenSession(gomock.Any(), gomock.Any(), gomock.Any()).Return(ar, nil)
67 ar.EXPECT().GetClient().Return(&fosite.DefaultClient{ID: "foo"})
68 },
69 },
70 {
71 description: "should pass - refresh token discovery first; refresh token found",
72 expectErr: nil,
73 client: &fosite.DefaultClient{ID: "bar"},
74 mock: func() {
75 token = "foo"
76 tokenType = fosite.RefreshToken
77 rtStrat.EXPECT().RefreshTokenSignature(token)
78 store.EXPECT().GetRefreshTokenSession(gomock.Any(), gomock.Any(), gomock.Any()).Return(ar, nil)
79 ar.EXPECT().GetID()
80 ar.EXPECT().GetClient().Return(&fosite.DefaultClient{ID: "bar"})
81 store.EXPECT().RevokeRefreshToken(gomock.Any(), gomock.Any())
82 store.EXPECT().RevokeAccessToken(gomock.Any(), gomock.Any())
83 },
84 },
85 {
86 description: "should pass - access token discovery first; access token found",
87 expectErr: nil,
88 client: &fosite.DefaultClient{ID: "bar"},
89 mock: func() {
90 token = "foo"
91 tokenType = fosite.AccessToken
92 atStrat.EXPECT().AccessTokenSignature(token)
93 store.EXPECT().GetAccessTokenSession(gomock.Any(), gomock.Any(), gomock.Any()).Return(ar, nil)
94 ar.EXPECT().GetID()
95 ar.EXPECT().GetClient().Return(&fosite.DefaultClient{ID: "bar"})
96 store.EXPECT().RevokeRefreshToken(gomock.Any(), gomock.Any())
97 store.EXPECT().RevokeAccessToken(gomock.Any(), gomock.Any())
98 },
99 },
100 {
101 description: "should pass - refresh token discovery first; refresh token not found",
102 expectErr: nil,
103 client: &fosite.DefaultClient{ID: "bar"},
104 mock: func() {
105 token = "foo"
106 tokenType = fosite.AccessToken
107 atStrat.EXPECT().AccessTokenSignature(token)
108 store.EXPECT().GetAccessTokenSession(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, fosite.ErrNotFound)
109
110 rtStrat.EXPECT().RefreshTokenSignature(token)
111 store.EXPECT().GetRefreshTokenSession(gomock.Any(), gomock.Any(), gomock.Any()).Return(ar, nil)
112 ar.EXPECT().GetID()
113 ar.EXPECT().GetClient().Return(&fosite.DefaultClient{ID: "bar"})
114 store.EXPECT().RevokeRefreshToken(gomock.Any(), gomock.Any())
115 store.EXPECT().RevokeAccessToken(gomock.Any(), gomock.Any())
116 },
117 },
118 {
119 description: "should pass - access token discovery first; access token not found",
120 expectErr: nil,
121 client: &fosite.DefaultClient{ID: "bar"},
122 mock: func() {
123 token = "foo"
124 tokenType = fosite.RefreshToken
125 rtStrat.EXPECT().RefreshTokenSignature(token)
126 store.EXPECT().GetRefreshTokenSession(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, fosite.ErrNotFound)
127
128 atStrat.EXPECT().AccessTokenSignature(token)
129 store.EXPECT().GetAccessTokenSession(gomock.Any(), gomock.Any(), gomock.Any()).Return(ar, nil)
130 ar.EXPECT().GetID()
131 ar.EXPECT().GetClient().Return(&fosite.DefaultClient{ID: "bar"})
132 store.EXPECT().RevokeRefreshToken(gomock.Any(), gomock.Any())
133 store.EXPECT().RevokeAccessToken(gomock.Any(), gomock.Any())
134 },
135 },
136 {
137 description: "should pass - refresh token discovery first; both tokens not found",
138 expectErr: nil,
139 client: &fosite.DefaultClient{ID: "bar"},
140 mock: func() {
141 token = "foo"
142 tokenType = fosite.RefreshToken
143 rtStrat.EXPECT().RefreshTokenSignature(token)
144 store.EXPECT().GetRefreshTokenSession(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, fosite.ErrNotFound)
145
146 atStrat.EXPECT().AccessTokenSignature(token)
147 store.EXPECT().GetAccessTokenSession(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, fosite.ErrNotFound)
148 },
149 },
150 {
151 description: "should pass - access token discovery first; both tokens not found",
152 expectErr: nil,
153 client: &fosite.DefaultClient{ID: "bar"},
154 mock: func() {
155 token = "foo"
156 tokenType = fosite.AccessToken
157 atStrat.EXPECT().AccessTokenSignature(token)
158 store.EXPECT().GetAccessTokenSession(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, fosite.ErrNotFound)
159
160 rtStrat.EXPECT().RefreshTokenSignature(token)
161 store.EXPECT().GetRefreshTokenSession(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, fosite.ErrNotFound)
162 },
163 },
164 {
165 description: "should fail - store error for access token get",
166 expectErr: fosite.ErrTemporarilyUnavailable,
167 client: &fosite.DefaultClient{ID: "bar"},
168 mock: func() {
169 token = "foo"
170 tokenType = fosite.AccessToken
171 atStrat.EXPECT().AccessTokenSignature(token)
172 store.EXPECT().GetAccessTokenSession(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, fmt.Errorf("random error"))
173
174 rtStrat.EXPECT().RefreshTokenSignature(token)
175 store.EXPECT().GetRefreshTokenSession(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, fosite.ErrNotFound)
176 },
177 },
178 {
179 description: "should fail - store error for refresh token get",
180 expectErr: fosite.ErrTemporarilyUnavailable,
181 client: &fosite.DefaultClient{ID: "bar"},
182 mock: func() {
183 token = "foo"
184 tokenType = fosite.RefreshToken
185 atStrat.EXPECT().AccessTokenSignature(token)
186 store.EXPECT().GetAccessTokenSession(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, fosite.ErrNotFound)
187
188 rtStrat.EXPECT().RefreshTokenSignature(token)
189 store.EXPECT().GetRefreshTokenSession(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, fmt.Errorf("random error"))
190 },
191 },
192 {
193 description: "should fail - store error for access token revoke",
194 expectErr: fosite.ErrTemporarilyUnavailable,
195 client: &fosite.DefaultClient{ID: "bar"},
196 mock: func() {
197 token = "foo"
198 tokenType = fosite.AccessToken
199 atStrat.EXPECT().AccessTokenSignature(token)
200 store.EXPECT().GetAccessTokenSession(gomock.Any(), gomock.Any(), gomock.Any()).Return(ar, nil)
201
202 ar.EXPECT().GetID()
203 ar.EXPECT().GetClient().Return(&fosite.DefaultClient{ID: "bar"})
204 store.EXPECT().RevokeRefreshToken(gomock.Any(), gomock.Any()).Return(fosite.ErrNotFound)
205 store.EXPECT().RevokeAccessToken(gomock.Any(), gomock.Any()).Return(fmt.Errorf("random error"))
206 },
207 },
208 {
209 description: "should fail - store error for refresh token revoke",
210 expectErr: fosite.ErrTemporarilyUnavailable,
211 client: &fosite.DefaultClient{ID: "bar"},
212 mock: func() {
213 token = "foo"
214 tokenType = fosite.RefreshToken
215 rtStrat.EXPECT().RefreshTokenSignature(token)
216 store.EXPECT().GetRefreshTokenSession(gomock.Any(), gomock.Any(), gomock.Any()).Return(ar, nil)
217
218 ar.EXPECT().GetID()
219 ar.EXPECT().GetClient().Return(&fosite.DefaultClient{ID: "bar"})
220 store.EXPECT().RevokeRefreshToken(gomock.Any(), gomock.Any()).Return(fmt.Errorf("random error"))
221 store.EXPECT().RevokeAccessToken(gomock.Any(), gomock.Any()).Return(fosite.ErrNotFound)
222 },
223 },
224 } {
225 t.Run(fmt.Sprintf("case=%d/description=%s", k, c.description), func(t *testing.T) {
226 c.mock()
227 err := h.RevokeToken(nil, token, tokenType, c.client)
228
229 if c.expectErr != nil {
230 require.EqualError(t, err, c.expectErr.Error())
231 } else {
232 require.NoError(t, err)
233 }
234 })
235 }
236 }
237
View as plain text