Skip to content

Commit

Permalink
40 send jwt as part of auth header in request (#44)
Browse files Browse the repository at this point in the history
  • Loading branch information
Koufan-De-King authored Nov 6, 2024
2 parents dafeea8 + cc6728b commit d13016b
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 9 deletions.
65 changes: 65 additions & 0 deletions src/services/keyManagement/__tests__/apiSercice.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import axios from "axios";
import MockAdapter from "axios-mock-adapter";
import { sendOTP } from "../apiService";

describe("sendOTP", () => {
let mock: MockAdapter; // Explicitly declare the type

beforeEach(() => {
mock = new MockAdapter(axios);
});

afterEach(() => {
mock.restore();
});

it("should send OTP successfully with valid inputs", async () => {
const fullPhoneNumber = "1234567890";
const jwtToken = "valid-token";

mock
.onPost("http://localhost:8080/api/registration")
.reply(200, { message: "OTP sent" });

const response = await sendOTP(fullPhoneNumber, jwtToken);

expect(response).toEqual({ message: "OTP sent" });
});

it("should throw an error when API responds with an error", async () => {
const fullPhoneNumber = "1234567890";
const jwtToken = "valid-token";

mock.onPost("http://localhost:8080/api/registration").reply(500);

await expect(sendOTP(fullPhoneNumber, jwtToken)).rejects.toThrow(
"Failed to send OTP",
);
});

it("should throw an error when an invalid JWT token is provided", async () => {
const fullPhoneNumber = "1234567890";
const jwtToken = "invalid-token";

mock.onPost("http://localhost:8080/api/registration").reply(401);

await expect(sendOTP(fullPhoneNumber, jwtToken)).rejects.toThrow(
"Failed to send OTP",
);
});

it("should handle empty phone number and JWT token", async () => {
await expect(sendOTP("", "")).rejects.toThrow("Failed to send OTP");
});

it("should handle network error", async () => {
const fullPhoneNumber = "1234567890";
const jwtToken = "valid-token";

mock.onPost("http://localhost:8080/api/registration").networkError();

await expect(sendOTP(fullPhoneNumber, jwtToken)).rejects.toThrow(
"Failed to send OTP",
);
});
});
6 changes: 4 additions & 2 deletions src/services/keyManagement/__tests__/jwtservice.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ describe("JWT Generation", () => {
// Convert privateKey to JWK for use with generateJWT
const privateKeyJWK = await jose.exportJWK(privateKey);

// Convert publicKey to JWK for verification
const publicKeyJWK = await jose.exportJWK(publicKey);

// Step 3: Call the generateJWT function
const jwt = await generateJWT(data, privateKeyJWK);
const jwt = await generateJWT(data, privateKeyJWK, publicKeyJWK);

// Step 4: Verify the JWT signature and payload
const publicKeyJWK = await jose.exportJWK(publicKey); // Convert publicKey to JWK for verification
const { payload } = await jose.jwtVerify(
jwt,
await jose.importJWK(publicKeyJWK, "ES256"),
Expand Down
27 changes: 27 additions & 0 deletions src/services/keyManagement/apiService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import axios from "axios";
export const sendOTP = async (fullPhoneNumber: string, jwtToken: string) => {
// Create the request object with both phone number and public key
const requestBody = {
phoneNumber: fullPhoneNumber,
};
const headers = {
"Content-Type": "application/json",
Authorization: `Bearer ${jwtToken}`,
};

try {
const response = await axios.post(
"http://localhost:8080/api/registration",
requestBody,
{ headers },
);

// Log the response from the backend
console.log("Response from backend:", response.data);

return response.data;
} catch (error) {
console.error("Error sending OTP:", error);
throw new Error("Failed to send OTP");
}
};
7 changes: 6 additions & 1 deletion src/services/keyManagement/jwtService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ function hashPayload(payload: string): string {
export async function generateJWT(
data: string,
privateKeyJWK: jose.JWK,
publicKeyJWK: jose.JWK,
): Promise<string> {
// Hash the payload
const hashedPayload = hashPayload(data);
Expand All @@ -23,7 +24,11 @@ export async function generateJWT(

// Sign the JWT with the private key
const jwt = await new jose.SignJWT(jwtPayload)
.setProtectedHeader({ alg: "ES256" })
.setProtectedHeader({
typ: "JWT",
alg: "ES256",
jwk: publicKeyJWK,
})
.sign(privateKey);

return jwt;
Expand Down
7 changes: 5 additions & 2 deletions src/services/keyManagement/registerService.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { generateJWT } from "./jwtService";
import storeKeyPair, { retrieveKeyPair } from "./storeKey";
import checkKeyPairExists from "./checkKeyPairExists";
import { sendOTP } from "./apiService";

export async function sendOtpWithKeyManagement(
phoneNumber: string,
Expand All @@ -20,8 +21,10 @@ export async function sendOtpWithKeyManagement(
}

// Generate JWT with the full phone number
jwtToken = await generateJWT(phoneNumber, privateKey);
console.log("Generated JWT:", jwtToken);
jwtToken = await generateJWT(phoneNumber, privateKey, publicKey);

// Send the JWT and phone number
await sendOTP(phoneNumber, jwtToken);
} else {
console.log("Key pair already exists. Skipping generation.");
}
Expand Down
7 changes: 3 additions & 4 deletions src/services/keyManagement/storeKey.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import storage from "./storageSetup";
import generateKeyPair from "./generateKey";
import storage from "./storageSetup"; // Import the initialized storage
import generateKeyPair from "./generateKey"; // Import your existing key generation function

// Function to store a key pair in IndexedDB
export async function storeKeyPair() {
const { publicKey, privateKey, kid } = await generateKeyPair();
const { publicKey, privateKey } = await generateKeyPair();

// Store both keys in a single record in IndexedDB
await storage.insert("keys", {
value: {
id: kid,
pub: { ...publicKey },
priv: { ...privateKey },
},
Expand Down

0 comments on commit d13016b

Please sign in to comment.