Hugo Pointcheval 25cf9518f9
All checks were successful
continuous-integration/drone/push Build is passing
chore: fix all problems
2023-02-24 10:12:04 +01:00

295 lines
8.1 KiB
Dart

// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'dart:async';
import 'dart:io';
import 'package:wyatt_http_client/wyatt_http_client.dart';
String lastToken = '';
int token = 0;
void printAuth(HttpRequest req) {
print(
'Authorization => '
"${req.headers.value('Authorization') ?? 'no authorization header'}",
);
}
Future<void> handleBasic(HttpRequest req) async {
printAuth(req);
}
Future<void> handleBasicNegotiate(HttpRequest req) async {
if (req.headers.value('Authorization') == null) {
req.response.statusCode = HttpStatus.unauthorized.statusCode;
req.response.headers.set(HeaderKeys.wwwAuthenticate, 'Basic realm="Wyatt"');
print(req.response.headers.value('WWW-Authenticate'));
return req.response.close();
}
printAuth(req);
}
Future<void> handleBearer(HttpRequest req) async {
printAuth(req);
}
Future<void> handleDigest(HttpRequest req) async {
if (req.headers.value('Authorization') == null) {
req.response.statusCode = HttpStatus.unauthorized.statusCode;
req.response.headers.set(
'WWW-Authenticate',
'Digest realm="Wyatt", '
'qop="auth,auth-int", '
'nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", '
'opaque="5ccc069c403ebaf9f0171e9517f40e41"',
);
print(req.response.headers.value('WWW-Authenticate'));
return req.response.close();
}
printAuth(req);
}
Future<void> handleUnsafe(HttpRequest req) async {
print(
'Query parameters => '
'${req.uri.queryParameters}',
);
}
Future<void> handleOauth2RefreshToken(HttpRequest req) async {
final action = req.uri.queryParameters['action'];
if (action == null) {
printAuth(req);
}
switch (action) {
case 'login':
if (req.method == 'POST') {
token++;
req.response.write(
'{"accessToken": "access-token-awesome$token", '
'"refreshToken": "refresh-token-awesome$token"}',
);
}
break;
case 'refresh':
printAuth(req);
if (req.method == 'GET') {
token++;
req.response.write('{"accessToken": "access-token-refreshed$token"}');
}
break;
case 'access-denied':
final String receivedToken = req.headers.value('Authorization') ?? '';
if (receivedToken != '' &&
lastToken != '' &&
receivedToken != lastToken) {
lastToken = receivedToken;
printAuth(req);
return req.response.close();
} else {
lastToken = receivedToken;
req.response.statusCode = HttpStatus.unauthorized.statusCode;
return req.response.close();
}
default:
break;
}
}
Future<void> server() async {
final server = await HttpServer.bind(InternetAddress.anyIPv6, 8080);
var error = 0;
var token = 0;
await server.forEach((request) {
print('[${request.method}] ${request.uri}');
switch (request.uri.path) {
case '/test/basic-test':
handleBasic(request);
break;
case '/test/basic-test-with-negotiate':
handleBasicNegotiate(request);
break;
case '/test/digest-test':
handleDigest(request);
break;
case '/test/apikey-test':
handleBearer(request);
break;
case '/test/bearer-test':
handleBearer(request);
break;
case '/test/unsafe-test':
handleUnsafe(request);
break;
case '/test/oauth2-test':
handleOauth2RefreshToken(request);
break;
case '/test/bearer-login':
if (request.method == 'POST') {
request.response.write('{"token": "access-token-test"}');
}
break;
case '/test/oauth2-test-error':
error++;
print('Error $error');
if (error >= 3) {
print('Authorized');
error = 0;
} else {
request.response.statusCode = HttpStatus.unauthorized.statusCode;
}
break;
case '/test/oauth2-test-timeout':
error++;
print('Error $error');
request.response.statusCode = HttpStatus.unauthorized.statusCode;
break;
case '/test/oauth2-login':
if (request.method == 'POST') {
token++;
request.response.write(
'{"accessToken": "access-token-awesome$token", '
'"refreshToken": "refresh-token-awesome$token"}',
);
}
break;
case '/test/oauth2-refresh':
print(
'Authorization => '
"${request.headers.value('Authorization') ?? 'no refresh token'}",
);
if (request.method == 'GET') {
token++;
request.response
.write('{"accessToken": "access-token-refreshed$token"}');
}
break;
case '/test/oauth2-refresh-error':
request.response.statusCode = HttpStatus.unauthorized.statusCode;
break;
default:
print(' => Unknown path or method');
request.response.statusCode = HttpStatus.notFound.statusCode;
}
request.response.close();
print('====================');
});
}
Future<void> main() async {
unawaited(server());
const base = 'localhost:8080';
final uriPrefix = UriPrefixMiddleware(
protocol: Protocols.http,
authority: base,
);
final jsonEncoder = BodyToJsonMiddleware();
final logger = SimpleLoggerMiddleware();
// Basic
final basicAuth = BasicAuthMiddleware(
username: 'username',
password: 'password',
);
final basic = MiddlewareClient(
pipeline: Pipeline.fromIterable([
uriPrefix,
basicAuth,
logger,
]),
);
await basic.get(Uri.parse('/test/basic-test'));
// Digest
final digestAuth = DigestAuthMiddleware(
username: 'Mufasa',
password: 'Circle Of Life',
);
final digest = MiddlewareClient(
pipeline: Pipeline.fromIterable([
uriPrefix,
digestAuth,
logger,
]),
);
await digest.get(Uri.parse('/test/digest-test'));
// // Bearer
// final bearer = BearerAuthenticationClient(
// token: 'access-token-test',
// inner: restClient,
// );
// await bearer.get(Uri.parse('/test/bearer-test'));
// // API Key
// final apiKey = BearerAuthenticationClient(
// token: 'awesome-api-key',
// authenticationMethod: 'ApiKey',
// inner: restClient,
// );
// await apiKey.get(Uri.parse('/test/apikey-test'));
// Unsafe URL
final unsafeAuth = UnsafeAuthMiddleware(
username: 'Mufasa',
password: 'Circle Of Life',
);
final unsafe = MiddlewareClient(
pipeline: Pipeline.fromIterable([
uriPrefix,
unsafeAuth,
logger,
]),
);
await unsafe.get(Uri.parse('/test/unsafe-test'));
// OAuth2
final refreshTokenAuth = RefreshTokenAuthMiddleware(
authorizationEndpoint: '/test/oauth2-test?action=login',
tokenEndpoint: '/test/oauth2-test?action=refresh',
accessTokenParser: (body) => body['accessToken']! as String,
refreshTokenParser: (body) => body['refreshToken']! as String,
);
final refreshToken = MiddlewareClient(
pipeline: Pipeline.fromIterable([
uriPrefix,
jsonEncoder,
refreshTokenAuth,
logger,
]),
);
await refreshToken.get(Uri.parse('/test/oauth2-test'));
// Login
await refreshToken.post(
Uri.parse('/test/oauth2-test'),
body: <String, String>{
'username': 'username',
'password': 'password',
},
);
await refreshToken.get(Uri.parse('/test/oauth2-test'));
// await refreshToken.refresh();
// await refreshToken.get(Uri.parse('/test/oauth2-test'));
// await refreshToken.get(Uri.parse('/test/oauth2-test?action=access-denied'));
exit(0);
}