32-Auth-and-issuer-OIDC-authorization_code.t 12 KB
Newer Older
Yadd's avatar
Yadd committed
1
2
3
4
5
6
7
8
9
use Test::More;
use strict;
use IO::String;
use MIME::Base64;

BEGIN {
    require 't/test-lib.pm';
}

Yadd's avatar
Yadd committed
10
my $debug = 'error';
Yadd's avatar
Yadd committed
11
12
my ( $op, $rp, $res );
my %handlerOR = ( op => [], rp => [] );
Yadd's avatar
Yadd committed
13
14

# Initialization
Yadd's avatar
Yadd committed
15
ok( $op = op(), 'OP portal' );
Yadd's avatar
Yadd committed
16

Yadd's avatar
Yadd committed
17
ok( $res = $op->_get('/oauth2/jwks'), 'Get JWKS,     endpoint /oauth2/jwks' );
Yadd's avatar
Yadd committed
18
19
my $jwks = $res->[2]->[0];

Yadd's avatar
Yadd committed
20
ok(
Yadd's avatar
Yadd committed
21
    $res = $op->_get('/.well-known/openid-configuration'),
Yadd's avatar
Yadd committed
22
23
    'Get metadata, endpoint /.well-known/openid-configuration'
);
Yadd's avatar
Yadd committed
24
25
my $metadata = $res->[2]->[0];
count(3);
Yadd's avatar
Yadd committed
26

Yadd's avatar
Yadd committed
27
28
switch ('rp');
ok( $rp = rp( $jwks, $metadata ), 'RP portal' );
Yadd's avatar
Yadd committed
29
30
count(1);

Yadd's avatar
Yadd committed
31
# Query RP for auth
Yadd's avatar
Yadd committed
32
ok( $res = $rp->_get( '/', accept => 'text/html' ), 'Unauth SP request' );
Yadd's avatar
Yadd committed
33
34
35
36
37
count(1);
my ( $url, $query ) =
  expectRedirection( $res, qr#http://auth.op.com(/oauth2/authorize)\?(.*)$# );

# Push request to OP
Yadd's avatar
Yadd committed
38
39
switch ('op');
ok( $res = $op->_get( $url, query => $query, accept => 'text/html' ),
Yadd's avatar
Yadd committed
40
    "Push request to OP,         endpoint $url" );
Yadd's avatar
Yadd committed
41
42
43
44
45
46
count(1);
expectOK($res);

# Try to authenticate to IdP
$query = "user=dwho&password=dwho&$query";
ok(
Yadd's avatar
Yadd committed
47
    $res = $op->_post(
Yadd's avatar
Yadd committed
48
49
50
51
52
        $url,
        IO::String->new($query),
        accept => 'text/html',
        length => length($query),
    ),
Yadd's avatar
Yadd committed
53
    "Post authentication,        endpoint $url"
Yadd's avatar
Yadd committed
54
55
56
57
);
count(1);
my $idpId = expectCookie($res);
my ( $host, $tmp );
Yadd's avatar
Yadd committed
58
( $host, $tmp, $query ) = expectForm( $res, '#', undef, 'confirm' );
Yadd's avatar
Yadd committed
59
60

ok(
Yadd's avatar
Yadd committed
61
    $res = $op->_post(
Yadd's avatar
Yadd committed
62
63
64
65
66
67
        $url,
        IO::String->new($query),
        accept => 'text/html',
        cookie => "lemonldap=$idpId",
        length => length($query),
    ),
Yadd's avatar
Yadd committed
68
    "Post confirmation,          endpoint $url"
Yadd's avatar
Yadd committed
69
70
71
72
73
74
);
count(1);

($query) = expectRedirection( $res, qr#^http://auth.rp.com/?\?(.*)$# );

# Push OP response to RP
Yadd's avatar
Yadd committed
75
switch ('rp');
Yadd's avatar
Yadd committed
76

Yadd's avatar
Yadd committed
77
ok( $res = $rp->_get( '/', query => $query, accept => 'text/html' ),
Yadd's avatar
Yadd committed
78
79
    'Call openidconnectcallback on RP' );
count(1);
Yadd's avatar
Yadd committed
80
81
my $spId = expectCookie($res);

Yadd's avatar
Yadd committed
82
switch ('op');
Yadd's avatar
Yadd committed
83
84
85
86
ok(
    $res = $op->_get( '/oauth2/checksession', accept => 'text.html' ),
    'Check session,           endpoint /oauth2/checksession'
);
Yadd's avatar
Yadd committed
87
count(1);
Yadd's avatar
Yadd committed
88
expectOK($res);
Yadd's avatar
Yadd committed
89

Yadd's avatar
Yadd committed
90
# Logout initiated by RP
Yadd's avatar
Yadd committed
91
switch ('rp');
Yadd's avatar
Yadd committed
92
ok(
Yadd's avatar
Yadd committed
93
    $res = $rp->_get(
Yadd's avatar
Yadd committed
94
95
96
97
98
99
100
101
102
103
104
105
        '/',
        query  => 'logout',
        cookie => "lemonldap=$spId",
        accept => 'text/html'
    ),
    'Query SP for logout'
);
count(1);
( $url, $query ) = expectRedirection( $res,
    qr#http://auth.op.com(/oauth2/logout)\?(post_logout_redirect_uri=.+)$# );

# Push logout to OP
Yadd's avatar
Yadd committed
106
switch ('op');
Yadd's avatar
Yadd committed
107
108

ok(
Yadd's avatar
Yadd committed
109
    $res = $op->_get(
Yadd's avatar
Yadd committed
110
111
112
113
114
        $url,
        query  => $query,
        cookie => "lemonldap=$idpId",
        accept => 'text/html'
    ),
Yadd's avatar
Yadd committed
115
    "Push logout request to OP,     endpoint $url"
Yadd's avatar
Yadd committed
116
117
118
119
120
121
);
count(1);

( $host, $tmp, $query ) = expectForm( $res, '#', undef, 'confirm' );

ok(
Yadd's avatar
Yadd committed
122
    $res = $op->_post(
Yadd's avatar
Yadd committed
123
124
125
126
        $url, IO::String->new($query),
        length => length($query),
        cookie => "lemonldap=$idpId",
    ),
Yadd's avatar
Yadd committed
127
128
129
130
131
132
133
134
135
136
137
138
    "Confirm logout,                endpoint $url"
);
count(1);

# Test logout endpoint without session
ok(
    $res = $op->_get(
        '/oauth2/logout',
        accept => 'text/html',
        query  => 'post_logout_redirect_uri=http://auth.rp.com'
    ),
    'logout endpoint with redirect, endpoint /oauth2/logout'
Yadd's avatar
Yadd committed
139
140
);
count(1);
Yadd's avatar
Yadd committed
141
142
143
144
145
146
expectRedirection( $res, 'http://auth.rp.com' );

ok( $res = $op->_get('/oauth2/logout'),
    'logout endpoint,               endpoint /oauth2/logout' );
count(1);
expectReject($res);
Yadd's avatar
Yadd committed
147

Yadd's avatar
Yadd committed
148
149
# Test if logout is done
ok(
Yadd's avatar
Yadd committed
150
    $res = $op->_get(
Yadd's avatar
Yadd committed
151
152
153
154
155
156
        '/', cookie => "lemonldap=$idpId",
    ),
    'Test if user is reject on IdP'
);
count(1);
expectReject($res);
Yadd's avatar
Yadd committed
157

Yadd's avatar
Yadd committed
158
switch ('rp');
Yadd's avatar
Yadd committed
159
ok(
Yadd's avatar
Yadd committed
160
    $res = $rp->_get(
Yadd's avatar
Yadd committed
161
162
163
164
165
166
167
168
169
170
        '/',
        accept => 'text/html',
        cookie =>
          "lemonldapidp=http://auth.idp.com/saml/metadata; lemonldap=$spId"
    ),
    'Test if user is reject on SP'
);
count(1);
expectRedirection( $res, qr#^http://auth.op.com/oauth2/authorize# );

Yadd's avatar
Yadd committed
171
#print STDERR Dumper($res);
Yadd's avatar
Yadd committed
172

Yadd's avatar
Yadd committed
173
174
175
clean_sessions();
done_testing( count() );

Yadd's avatar
Yadd committed
176
177
178
179
no warnings 'redefine';

sub LWP::UserAgent::request {
    my ( $self, $req ) = @_;
Yadd's avatar
Yadd committed
180
    ok( $req->uri =~ m#http://auth.((?:o|r)p).com(.*)#, ' REST request' );
Yadd's avatar
Yadd committed
181
182
    my $host = $1;
    my $url  = $2;
Yadd's avatar
Yadd committed
183
184
185
    my ( $res, $client );
    count(1);
    if ( $host eq 'op' ) {
Yadd's avatar
Yadd committed
186
        pass("  Request from RP to OP,     endpoint $url");
Yadd's avatar
Yadd committed
187
        $client = $op;
Yadd's avatar
Yadd committed
188
189
190
    }
    elsif ( $host eq 'rp' ) {
        pass('  Request from OP to RP');
Yadd's avatar
Yadd committed
191
        $client = $rp;
Yadd's avatar
Yadd committed
192
193
194
195
196
    }
    else {
        fail('  Aborting REST request (external)');
        return HTTP::Response->new(500);
    }
Yadd's avatar
Yadd committed
197
198
199
200
201
202
203
204
    if ( $req->method =~ /^post$/i ) {
        my $s = $req->content;
        ok(
            $res = $client->_post(
                $url, IO::String->new($s),
                length => length($s),
                type   => $req->header('Content-Type'),
            ),
Yadd's avatar
Yadd committed
205
            '  Execute request'
Yadd's avatar
Yadd committed
206
207
208
209
210
211
212
213
214
215
        );
    }
    else {
        ok(
            $res = $client->_get(
                $url,
                custom => {
                    HTTP_AUTHORIZATION => $req->header('Authorization'),
                }
            ),
Yadd's avatar
Yadd committed
216
            '  Execute request'
Yadd's avatar
Yadd committed
217
218
        );
    }
Yadd's avatar
Yadd committed
219
    ok( $res->[0] == 200, '  Response is 200' );
Yadd's avatar
Yadd committed
220
    ok( getHeader( $res, 'Content-Type' ) =~ m#^application/json#,
Yadd's avatar
Yadd committed
221
        '  Content is JSON' )
Yadd's avatar
Yadd committed
222
223
224
225
226
227
228
      or explain( $res->[1], 'Content-Type => application/json' );
    my $httpResp = HTTP::Response->new( $res->[0], 'OK' );

    while ( my $name = shift @{ $res->[1] } ) {
        $httpResp->header( $name, shift( @{ $res->[1] } ) );
    }
    $httpResp->content( join( '', @{ $res->[2] } ) );
Yadd's avatar
Yadd committed
229
    count(4);
Yadd's avatar
Yadd committed
230
231
232
    return $httpResp;
}

Yadd's avatar
Yadd committed
233
234
sub switch {
    my $type = shift;
Yadd's avatar
Yadd committed
235
236
    pass( '==> Switching to ' . uc($type) . ' <==' );
    count(1);
Yadd's avatar
Yadd committed
237
238
239
240
241
    @Lemonldap::NG::Handler::Main::Reload::_onReload = @{
        $handlerOR{$type};
    };
}

Yadd's avatar
Yadd committed
242
sub op {
Yadd's avatar
Yadd committed
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
    return LLNG::Manager::Test->new(
        {
            ini => {
                logLevel                        => $debug,
                domain                          => 'idp.com',
                portal                          => 'http://auth.op.com',
                authentication                  => 'Demo',
                userDB                          => 'Demo',
                issuerDBOpenIDConnectActivation => "1",
                oidcRPMetaDataExportedVars      => {
                    rp => {
                        email       => "mail",
                        family_name => "cn",
                        name        => "cn"
                    }
                },
                oidcServiceMetaDataIssuer             => "http://auth.op.com",
                oidcServiceMetaDataAuthorizeURI       => "authorize",
                oidcServiceMetaDataCheckSessionURI    => "checksession",
                oidcServiceMetaDataJWKSURI            => "jwks",
                oidcServiceMetaDataEndSessionURI      => "logout",
                oidcServiceMetaDataRegistrationURI    => "register",
                oidcServiceMetaDataTokenURI           => "token",
                oidcServiceMetaDataUserInfoURI        => "userinfo",
                oidcServiceAllowHybridFlow            => 1,
                oidcServiceAllowImplicitFlow          => 1,
                oidcServiceAllowDynamicRegistration   => 1,
                oidcServiceAllowAuthorizationCodeFlow => 1,
                oidcRPMetaDataOptions                 => {
                    rp => {
Yadd's avatar
Yadd committed
273
274
275
276
277
278
279
                        oidcRPMetaDataOptionsDisplayName       => "RP",
                        oidcRPMetaDataOptionsIDTokenExpiration => 3600,
                        oidcRPMetaDataOptionsClientID          => "rpid",
                        oidcRPMetaDataOptionsIDTokenSignAlg    => "HS512",
                        oidcRPMetaDataOptionsBypassConsent     => 0,
                        oidcRPMetaDataOptionsClientSecret      => "rpsecret",
                        oidcRPMetaDataOptionsUserIDAttr        => "",
Yadd's avatar
Yadd committed
280
281
282
283
284
285
286
287
288
289
290
291
292
293
                        oidcRPMetaDataOptionsAccessTokenExpiration => 3600
                    }
                },
                oidcOPMetaDataOptions           => {},
                oidcOPMetaDataJSON              => {},
                oidcOPMetaDataJWKS              => {},
                oidcStorageOptions              => {},
                oidcServiceMetaDataAuthnContext => {
                    'loa-4' => 4,
                    'loa-1' => 1,
                    'loa-5' => 5,
                    'loa-2' => 2,
                    'loa-3' => 3
                },
Yadd's avatar
Yadd committed
294
                oidcServicePrivateKeySig => "-----BEGIN RSA PRIVATE KEY-----
Yadd's avatar
Yadd committed
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
MIIEowIBAAKCAQEAs2jsmIoFuWzMkilJaA8//5/T30cnuzX9GImXUrFR2k9EKTMt
GMHCdKlWOl3BV+BTAU9TLz7Jzd/iJ5GJ6B8TrH1PHFmHpy8/qE/S5OhinIpIi7eb
ABqnoVcwDdCa8ugzq8k8SWxhRNXfVIlwz4NH1caJ8lmiERFj7IvNKqEhzAk0pyDr
8hubveTC39xREujKlsqutpPAFPJ3f2ybVsdykX5rx0h5SslG3jVWYhZ/SOb2aIzO
r0RMjhQmsYRwbpt3anjlBZ98aOzg7GAkbO8093X5VVk9vaPRg0zxJQ0Do0YLyzkR
isSAIFb0tdKuDnjRGK6y/N2j6At2HjkxntbtGQIDAQABAoIBADYq6LxJd977LWy3
0HT9nboFPIf+SM2qSEc/S5Po+6ipJBA4ZlZCMf7dHa6znet1TDpqA9iQ4YcqIHMH
6xZNQ7hhgSAzG9TrXBHqP+djDlrrGWotvjuy0IfS9ixFnnLWjrtAH9afRWLuG+a/
NHNC1M6DiiTE0TzL/lpt/zzut3CNmWzH+t19X6UsxUg95AzooEeewEYkv25eumWD
mfQZfCtSlIw1sp/QwxeJa/6LJw7KcPZ1wXUm1BN0b9eiKt9Cmni1MS7elgpZlgGt
xtfGTZtNLQ7bgDiM8MHzUfPBhbceNSIx2BeCuOCs/7eaqgpyYHBbAbuBQex2H61l
Lcc3Tz0CgYEA4Kx/avpCPxnvsJ+nHVQm5d/WERuDxk4vH1DNuCYBvXTdVCGADf6a
F5No1JcTH3nPTyPWazOyGdT9LcsEJicLyD8vCM6hBFstG4XjqcAuqG/9DRsElpHQ
yi1zc5DNP7Vxmiz9wII0Mjy0abYKtxnXh9YK4a9g6wrcTpvShhIcIb8CgYEAzGzG
lorVCfX9jXULIznnR/uuP5aSnTEsn0xJeqTlbW0RFWLdj8aIL1peirh1X89HroB9
GeTNqEJXD+3CVL2cx+BRggMDUmEz4hR59meZCDGUyT5fex4LIsceb/ESUl2jo6Sw
HXwWbN67rQ55N4oiOcOppsGxzOHkl5HdExKidycCgYEAr5Qev2tz+fw65LzfzHvH
Kj4S/KuT/5V6He731cFd+sEpdmX3vPgLVAFPG1Q1DZQT/rTzDDQKK0XX1cGiLG63
NnaqOye/jbfzOF8Z277kt51NFMDYhRLPKDD82IOA4xjY/rPKWndmcxwdob8yAIWh
efY76sMz6ntCT+xWSZA9i+ECgYBWMZM2TIlxLsBfEbfFfZewOUWKWEGvd9l5vV/K
D5cRIYivfMUw5yPq2267jPUolayCvniBH4E7beVpuPVUZ7KgcEvNxtlytbt7muil
5Z6X3tf+VodJ0Swe2NhTmNEB26uwxzLe68BE3VFCsbSYn2y48HAq+MawPZr18bHG
ZfgMxwKBgHHRg6HYqF5Pegzk1746uH2G+OoCovk5ylGGYzcH2ghWTK4agCHfBcDt
EYqYAev/l82wi+OZ5O8U+qjFUpT1CVeUJdDs0o5u19v0UJjunU1cwh9jsxBZAWLy
PAGd6SWf4S3uQCTw6dLeMna25YIlPh5qPA6I/pAahe8e3nSu2ckl
-----END RSA PRIVATE KEY-----
",
Yadd's avatar
Yadd committed
322
                oidcServicePublicKeySig => "-----BEGIN PUBLIC KEY-----
Yadd's avatar
Yadd committed
323
324
325
326
327
328
329
330
331
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs2jsmIoFuWzMkilJaA8/
/5/T30cnuzX9GImXUrFR2k9EKTMtGMHCdKlWOl3BV+BTAU9TLz7Jzd/iJ5GJ6B8T
rH1PHFmHpy8/qE/S5OhinIpIi7ebABqnoVcwDdCa8ugzq8k8SWxhRNXfVIlwz4NH
1caJ8lmiERFj7IvNKqEhzAk0pyDr8hubveTC39xREujKlsqutpPAFPJ3f2ybVsdy
kX5rx0h5SslG3jVWYhZ/SOb2aIzOr0RMjhQmsYRwbpt3anjlBZ98aOzg7GAkbO80
93X5VVk9vaPRg0zxJQ0Do0YLyzkRisSAIFb0tdKuDnjRGK6y/N2j6At2Hjkxntbt
GQIDAQAB
-----END PUBLIC KEY-----
",
Yadd's avatar
Yadd committed
332
333
334
335
            }
        }
    );
}
Yadd's avatar
Yadd committed
336

Yadd's avatar
Yadd committed
337
sub rp {
Yadd's avatar
Yadd committed
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
    my ( $jwks, $metadata ) = @_;
    return LLNG::Manager::Test->new(
        {
            ini => {
                logLevel                   => $debug,
                domain                     => 'rp.com',
                portal                     => 'http://auth.rp.com',
                authentication             => 'OpenIDConnect',
                userDB                     => 'OpenIDConnect',
                oidcOPMetaDataExportedVars => {
                    op => {
                        cn   => "name",
                        uid  => "sub",
                        sn   => "family_name",
                        mail => "email"
                    }
                },
                oidcOPMetaDataOptions => {
                    op => {
                        oidcOPMetaDataOptionsJWKSTimeout  => 0,
                        oidcOPMetaDataOptionsClientSecret => "rpsecret",
                        oidcOPMetaDataOptionsScope        => "openid profile",
                        oidcOPMetaDataOptionsStoreIDToken => 0,
                        oidcOPMetaDataOptionsDisplay      => "",
                        oidcOPMetaDataOptionsClientID     => "rpid",
                        oidcOPMetaDataOptionsConfigurationURI =>
                          "https://auth.op.com/.well-known/openid-configuration"
                    }
                },
                oidcOPMetaDataJWKS => {
                    op => $jwks,
                },
                oidcOPMetaDataJSON => {
                    op => $metadata,
                }
            }
        }
    );
}