Skip to content

Commit

Permalink
get authenticated profile id
Browse files Browse the repository at this point in the history
  • Loading branch information
krzysu committed Sep 19, 2023
1 parent f3946c0 commit 9b77bec
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 11 deletions.
4 changes: 4 additions & 0 deletions examples/node/scripts/authenticate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ async function main() {
const accessTokenResult = await client.authentication.getAccessToken();
const accessToken = accessTokenResult.unwrap();

const profileIdResult = await client.authentication.getProfileId();
const profileId = profileIdResult.unwrap();

console.log(`Is LensClient authenticated? `, await client.authentication.isAuthenticated());
console.log(`Authenticated profileId: `, profileId);
console.log(`Access token: `, accessToken);
console.log(`Is access token valid? `, await client.authentication.verify(accessToken));
}
Expand Down
12 changes: 8 additions & 4 deletions examples/node/scripts/profile/changeProfileManagers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ import { setupWallet } from '../shared/setupWallet';

async function main() {
const wallet = setupWallet();
const lensClient = await getAuthenticatedClientFromEthersWallet(wallet);
const client = await getAuthenticatedClientFromEthersWallet(wallet);

const typedDataResult = await lensClient.profile.createChangeProfileManagersTypedData({
const profileIdResult = await client.authentication.getProfileId();
const profileId = profileIdResult.unwrap();

const typedDataResult = await client.profile.createChangeProfileManagersTypedData({
approveLensManager: true,
// changeManagers: [
// {
Expand All @@ -27,7 +30,7 @@ async function main() {
);

// broadcast onchain
const broadcastOnchainResult = await lensClient.transaction.broadcastOnchain({
const broadcastOnchainResult = await client.transaction.broadcastOnchain({
id,
signature: signedTypedData,
});
Expand All @@ -40,7 +43,8 @@ async function main() {
}

console.log(
`Successfully changed profile managers with transaction with id ${onchainRelayResult.txId}, txHash: ${onchainRelayResult.txHash}`,
`Successfully changed profile manager for profile ${profileId} with: `,
onchainRelayResult,
);
}

Expand Down
15 changes: 15 additions & 0 deletions packages/client/src/authentication/Authentication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,21 @@ export class Authentication implements IAuthentication {
return failure(new CredentialsExpiredError());
}

async getProfileId(): PromiseResult<string, CredentialsExpiredError | NotAuthenticatedError> {
const credentials = await this.storage.get();

if (!credentials) {
return failure(new NotAuthenticatedError());
}

if (!credentials.canRefresh()) {
return failure(new CredentialsExpiredError());
}

return success(credentials.getProfileId());
}

// private methods
async getRequestHeader(): PromiseResult<
Record<string, string>,
CredentialsExpiredError | NotAuthenticatedError
Expand Down
7 changes: 7 additions & 0 deletions packages/client/src/authentication/IAuthentication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,11 @@ export interface IAuthentication {
* @returns The access token
*/
getAccessToken(): PromiseResult<string, CredentialsExpiredError | NotAuthenticatedError>;

/**
* Get the profileId of authenticated profile.
*
* @returns The access token
*/
getProfileId(): PromiseResult<string, CredentialsExpiredError | NotAuthenticatedError>;
}
16 changes: 12 additions & 4 deletions packages/client/src/authentication/adapters/Credentials.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,25 @@ import { DateUtils } from '@lens-protocol/shared-kernel';
import { Credentials } from './Credentials';

const accessToken =
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjB4YjE5QzI4OTBjZjk0N0FEM2YwYjdkN0U1QTlmZkJjZTM2ZDNmOWJkMiIsInJvbGUiOiJub3JtYWwiLCJpYXQiOjE2Mzc3NTQ2ODEsImV4cCI6MTYzNzc1NDc0MX0.Be1eGBvVuFL4fj4pHHqc0yWDledsgS2GP3Jgonmy-xw';
const accessTokenExp = 1637754741000;
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjB4MWEiLCJldm1BZGRyZXNzIjoiMHhhNTY1M2U4OEQ5YzM1MjM4N2RlRGRDNzliY2Y5OWYwYWRhNjJlOWM2Iiwicm9sZSI6Im5vcm1hbCIsImlhdCI6MTY5NTEzMzMxNywiZXhwIjoxNjk1MTM1MTE3fQ.6s4-ClaPmUMuvYhZ7MaVrSwu-Axzkv1vCkKGtIqnnGo';
const accessTokenExp = 1695135117000;
const refreshToken =
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjB4YjE5QzI4OTBjZjk0N0FEM2YwYjdkN0U1QTlmZkJjZTM2ZDNmOWJkMiIsInJvbGUiOiJyZWZyZXNoIiwiaWF0IjoxNjM3NzU0NjgxLCJleHAiOjE2Mzc3NTQ5ODF9.3SqgsVMyqFPBcem2W9Iog91SWC8cIAFixXBkDue73Rc';
const refreshTokenExp = 1637754981000;
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjB4MWEiLCJldm1BZGRyZXNzIjoiMHhhNTY1M2U4OEQ5YzM1MjM4N2RlRGRDNzliY2Y5OWYwYWRhNjJlOWM2Iiwicm9sZSI6InJlZnJlc2giLCJpYXQiOjE2OTUxMzMzMTcsImV4cCI6MTY5NTczODExN30.wgdJ_bJs50CL1lGs_sjaBYrYEvsh-h8Qj0Yv1CLpQR4';
const refreshTokenExp = 1695738117000;

describe(`Given the ${Credentials.name} class`, () => {
afterAll(() => {
jest.useRealTimers();
});

describe(`when ${Credentials.prototype.getProfileId.name} is invoked`, () => {
it(`should return a profile id`, async () => {
const credentials = new Credentials(undefined, refreshToken);

expect(credentials.getProfileId()).toBe('0x1a');
});
});

describe(`when ${Credentials.prototype.canRefresh.name} is invoked`, () => {
it(`should return true if refresh token is not yet expired`, async () => {
const credentials = new Credentials(undefined, refreshToken);
Expand Down
21 changes: 18 additions & 3 deletions packages/client/src/authentication/adapters/Credentials.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { DateUtils, invariant } from '@lens-protocol/shared-kernel';
import jwtDecode, { JwtPayload } from 'jwt-decode';
import jwtDecode from 'jwt-decode';

export class ClockSkewedError extends Error {
name = 'ClockSkewedError' as const;
Expand All @@ -11,14 +11,22 @@ const TOKEN_EXP_THRESHOLD = DateUtils.secondsToMs(30);

const CLOCK_SKEWED_THRESHOLD = DateUtils.secondsToMs(10);

type LensJwtPayload = {
id: string;
evmAddress: string;
role: string;
iat: number;
exp: number;
};

export class Credentials {
constructor(
readonly accessToken: string | undefined,
readonly refreshToken: string,
) {}

checkClock() {
const decodedToken = jwtDecode<JwtPayload>(this.refreshToken);
const decodedToken = jwtDecode<LensJwtPayload>(this.refreshToken);
invariant(decodedToken.iat, 'Issued at date should be provided by JWT token');

// check if local time is not too far off from server time
Expand Down Expand Up @@ -47,8 +55,15 @@ export class Credentials {
return now >= tokenExpTimestamp - TOKEN_EXP_THRESHOLD;
}

getProfileId(): string {
const decodedToken = jwtDecode<LensJwtPayload>(this.refreshToken);
invariant(decodedToken.id, 'ProfileId should be provided by JWT token');

return decodedToken.id;
}

private getTokenExpTimestamp(token: string) {
const decodedToken = jwtDecode<JwtPayload>(token);
const decodedToken = jwtDecode<LensJwtPayload>(token);

invariant(decodedToken.exp, 'Exp date should be provided by JWT token');

Expand Down

0 comments on commit 9b77bec

Please sign in to comment.