JWT refactor

This commit is contained in:
Ankit Mahato
2025-07-12 23:36:27 +05:30
parent 1e10606ebf
commit 32dcbda803
3 changed files with 80 additions and 55 deletions

View File

@@ -1,4 +1,6 @@
const kEmpty = ''; const kEmpty = '';
// API Key Auth
const kApiKeyHeaderName = 'x-api-key'; const kApiKeyHeaderName = 'x-api-key';
const kAddToLocations = [ const kAddToLocations = [
('header', 'Header'), ('header', 'Header'),
@@ -12,11 +14,14 @@ const kHintTextFieldName = "Header/Query Param Name";
const kLabelApiKey = "API Key"; const kLabelApiKey = "API Key";
const kHintTextKey = "Key"; const kHintTextKey = "Key";
// Username-password auth
const kHintUsername = "Username"; const kHintUsername = "Username";
const kHintPassword = "Password"; const kHintPassword = "Password";
// Bearer Token AUth
const kHintToken = "Token"; const kHintToken = "Token";
// Digest Auth
const kInfoDigestUsername = const kInfoDigestUsername =
"Your username for digest authentication. This will be sent to the server for credential verification."; "Your username for digest authentication. This will be sent to the server for credential verification.";
const kInfoDigestPassword = const kInfoDigestPassword =
@@ -35,3 +40,25 @@ const kInfoDigestQop =
const kHintDataString = "Opaque"; const kHintDataString = "Opaque";
const kInfoDigestDataString = const kInfoDigestDataString =
"Server-specified data string that should be returned unchanged in the authorization header. Usually obtained from server's 401 response."; "Server-specified data string that should be returned unchanged in the authorization header. Usually obtained from server's 401 response.";
// JWT Auth
const kMsgAddToken = "Add JWT token to";
const kTooltipTokenAddTo = "Select where to add JWT token";
const kTextAlgo = "Algorithm";
const kTooltipJWTAlgo = "Select JWT algorithm";
const kStartAlgo = "HS";
const kHintSecret = "Secret Key";
const kInfoSecret =
"The secret key used to sign the JWT token. Keep this secure and match it with your server configuration.";
const kMsgSecret = "Secret is Base64 encoded";
const kMsgPrivateKey = "Private Key";
const kHintRSA = '''
-----BEGIN RSA PRIVATE KEY-----
Private Key in PKCS#8 PEM Format
-----END RSA PRIVATE KEY-----
''';
const kMsgPayload = "Payload (JSON format)";
const kHintJson =
'{"sub": "1234567890", "name": "John Doe", "iat": 1516239022}';
const kHeaderPrefix = 'Bearer';
const kQueryParamKey = 'token';

View File

@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:apidash_core/apidash_core.dart'; import 'package:apidash_core/apidash_core.dart';
import 'package:apidash_design_system/apidash_design_system.dart'; import 'package:apidash_design_system/apidash_design_system.dart';
import 'package:apidash/widgets/widgets.dart'; import 'package:apidash/widgets/widgets.dart';
import 'consts.dart';
class JwtAuthFields extends StatefulWidget { class JwtAuthFields extends StatefulWidget {
final AuthModel? authData; final AuthModel? authData;
@@ -34,8 +35,8 @@ class _JwtAuthFieldsState extends State<JwtAuthFields> {
_secretController = TextEditingController(text: jwt?.secret ?? ''); _secretController = TextEditingController(text: jwt?.secret ?? '');
_privateKeyController = TextEditingController(text: jwt?.privateKey ?? ''); _privateKeyController = TextEditingController(text: jwt?.privateKey ?? '');
_payloadController = TextEditingController(text: jwt?.payload ?? ''); _payloadController = TextEditingController(text: jwt?.payload ?? '');
_addTokenTo = jwt?.addTokenTo ?? 'header'; _addTokenTo = jwt?.addTokenTo ?? kAddToDefaultLocation;
_algorithm = jwt?.algorithm ?? 'HS256'; _algorithm = jwt?.algorithm ?? kJwtAlgos[0];
_isSecretBase64Encoded = jwt?.isSecretBase64Encoded ?? false; _isSecretBase64Encoded = jwt?.isSecretBase64Encoded ?? false;
} }
@@ -45,7 +46,7 @@ class _JwtAuthFieldsState extends State<JwtAuthFields> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
"Add JWT token to", kMsgAddToken,
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.normal, fontWeight: FontWeight.normal,
fontSize: 14, fontSize: 14,
@@ -53,13 +54,9 @@ class _JwtAuthFieldsState extends State<JwtAuthFields> {
), ),
SizedBox(height: 4), SizedBox(height: 4),
ADPopupMenu<String>( ADPopupMenu<String>(
value: value: kAddToLocationsMap[_addTokenTo],
_addTokenTo == 'header' ? 'Request Header' : 'Query Parameters', values: kAddToLocations,
values: const [ tooltip: kTooltipTokenAddTo,
('header', 'Request Header'),
('query', 'Query Parameters'),
],
tooltip: "Select where to add JWT token",
isOutlined: true, isOutlined: true,
onChanged: widget.readOnly onChanged: widget.readOnly
? null ? null
@@ -74,7 +71,7 @@ class _JwtAuthFieldsState extends State<JwtAuthFields> {
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
Text( Text(
"Algorithm", kTextAlgo,
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.normal, fontWeight: FontWeight.normal,
fontSize: 14, fontSize: 14,
@@ -83,23 +80,8 @@ class _JwtAuthFieldsState extends State<JwtAuthFields> {
SizedBox(height: 4), SizedBox(height: 4),
ADPopupMenu<String>( ADPopupMenu<String>(
value: _algorithm, value: _algorithm,
values: const [ values: kJwtAlgos.map((i) => (i, null)),
('HS256', 'HS256'), tooltip: kTooltipJWTAlgo,
('HS384', 'HS384'),
('HS512', 'HS512'),
('RS256', 'RS256'),
('RS384', 'RS384'),
('RS512', 'RS512'),
('PS256', 'PS256'),
('PS384', 'PS384'),
('PS512', 'PS512'),
('ES256', 'ES256'),
('ES256K', 'ES256K'),
('ES384', 'ES384'),
('ES512', 'ES512'),
('EdDSA', 'EdDSA'),
],
tooltip: "Select JWT algorithm",
isOutlined: true, isOutlined: true,
onChanged: widget.readOnly onChanged: widget.readOnly
? null ? null
@@ -113,20 +95,19 @@ class _JwtAuthFieldsState extends State<JwtAuthFields> {
}, },
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
if (_algorithm.startsWith('HS')) ...[ if (_algorithm.startsWith(kStartAlgo)) ...[
AuthTextField( AuthTextField(
readOnly: widget.readOnly, readOnly: widget.readOnly,
controller: _secretController, controller: _secretController,
isObscureText: true, isObscureText: true,
hintText: "Secret key", hintText: kHintSecret,
infoText: infoText: kInfoSecret,
"The secret key used to sign the JWT token. Keep this secure and match it with your server configuration.",
onChanged: (value) => _updateJwtAuth(), onChanged: (value) => _updateJwtAuth(),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
CheckboxListTile( CheckboxListTile(
title: Text( title: Text(
"Secret is Base64 encoded", kMsgSecret,
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.normal, fontWeight: FontWeight.normal,
fontSize: 14, fontSize: 14,
@@ -145,7 +126,7 @@ class _JwtAuthFieldsState extends State<JwtAuthFields> {
), ),
] else ...[ ] else ...[
Text( Text(
"Private Key", kMsgPrivateKey,
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.normal, fontWeight: FontWeight.normal,
fontSize: 14, fontSize: 14,
@@ -163,11 +144,7 @@ class _JwtAuthFieldsState extends State<JwtAuthFields> {
maxWidth: MediaQuery.sizeOf(context).width - 100, maxWidth: MediaQuery.sizeOf(context).width - 100,
), ),
contentPadding: const EdgeInsets.all(18), contentPadding: const EdgeInsets.all(18),
hintText: ''' hintText: kHintRSA,
-----BEGIN RSA PRIVATE KEY-----
Private Key in PKCS#8 PEM Format
-----END RSA PRIVATE KEY-----
''',
hintStyle: Theme.of(context).textTheme.bodyMedium, hintStyle: Theme.of(context).textTheme.bodyMedium,
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
@@ -188,7 +165,7 @@ Private Key in PKCS#8 PEM Format
], ],
const SizedBox(height: 16), const SizedBox(height: 16),
Text( Text(
"Payload (JSON format)", kMsgPayload,
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.normal, fontWeight: FontWeight.normal,
fontSize: 14, fontSize: 14,
@@ -206,8 +183,7 @@ Private Key in PKCS#8 PEM Format
maxWidth: MediaQuery.sizeOf(context).width - 100, maxWidth: MediaQuery.sizeOf(context).width - 100,
), ),
contentPadding: const EdgeInsets.all(18), contentPadding: const EdgeInsets.all(18),
hintText: hintText: kHintJson,
'{"sub": "1234567890", "name": "John Doe", "iat": 1516239022}',
hintStyle: Theme.of(context).textTheme.bodyMedium, hintStyle: Theme.of(context).textTheme.bodyMedium,
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
@@ -230,21 +206,26 @@ Private Key in PKCS#8 PEM Format
} }
void _updateJwtAuth() { void _updateJwtAuth() {
final jwt = AuthJwtModel(
secret: _secretController.text.trim(),
privateKey: _privateKeyController.text.trim(),
payload: _payloadController.text.trim(),
addTokenTo: _addTokenTo,
algorithm: _algorithm,
isSecretBase64Encoded: _isSecretBase64Encoded,
headerPrefix: kHeaderPrefix,
queryParamKey: kQueryParamKey,
header: '',
);
widget.updateAuth( widget.updateAuth(
widget.authData?.copyWith( widget.authData?.copyWith(
type: APIAuthType.jwt, type: APIAuthType.jwt,
jwt: AuthJwtModel( jwt: jwt,
secret: _secretController.text.trim(), ) ??
privateKey: _privateKeyController.text.trim(), AuthModel(
payload: _payloadController.text.trim(), type: APIAuthType.jwt,
addTokenTo: _addTokenTo, jwt: jwt,
algorithm: _algorithm, ),
isSecretBase64Encoded: _isSecretBase64Encoded,
headerPrefix: 'Bearer',
queryParamKey: 'token',
header: '',
),
),
); );
} }
} }

View File

@@ -26,6 +26,23 @@ enum APIAuthType {
const kDigestAlgos = ['MD5', 'MD5-sess', 'SHA-256', 'SHA-256-sess']; const kDigestAlgos = ['MD5', 'MD5-sess', 'SHA-256', 'SHA-256-sess'];
const kQop = ['auth', 'auth-int']; const kQop = ['auth', 'auth-int'];
const kJwtAlgos = [
'HS256',
'HS384',
'HS512',
'RS256',
'RS384',
'RS512',
'PS256',
'PS384',
'PS512',
'ES256',
'ES256K',
'ES384',
'ES512',
'EdDSA',
];
enum HTTPVerb { enum HTTPVerb {
get("GET"), get("GET"),
head("HEAD"), head("HEAD"),