Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: dart auth provider #405

Merged
merged 79 commits into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
753ed50
feat: structure
Jan 6, 2025
a5d3059
feat: working project scoped token
Jan 7, 2025
93f2eca
feat: example
Jan 7, 2025
c24c8d3
chore: revert import order change
Jan 7, 2025
8cdf0cd
chore: removed unused dotenv
Jan 7, 2025
cbdf317
fix: simplify Environment
hpelitebook745G2 Jan 8, 2025
776319e
fix: improve environment lookup
hpelitebook745G2 Jan 8, 2025
dcf7499
fix: make constructor private so only Environment class can make new …
hpelitebook745G2 Jan 8, 2025
9333dd9
fix: revert environments as public
hpelitebook745G2 Jan 8, 2025
a2e9ba6
feat: dart consumer auth provider (#407)
hpelitebook745G2 Jan 8, 2025
316233a
Merge branch 'dart-auth-provider' of https://github.com/affinidi/affi…
hpelitebook745G2 Jan 9, 2025
bbad90d
fix: add consumerCisUrl
hpelitebook745G2 Jan 9, 2025
4523ca7
feat: iota and improved examples with dotenv
Jan 9, 2025
5a1f265
feat: token refresh
Jan 10, 2025
72a30a4
feat: add JS wallet service from Vault
hpelitebook745G2 Jan 10, 2025
5772a59
fix: remove redundant Consumer base URL
hpelitebook745G2 Jan 10, 2025
c1077a2
feat: initial implementation of Consumer Auth Provider
hpelitebook745G2 Jan 10, 2025
9a677bc
feat: add temporary Token provider
hpelitebook745G2 Jan 10, 2025
02219f2
feat: add fetchConsumerCisUrl test
hpelitebook745G2 Jan 10, 2025
bd69cbe
fix: use seed instead of mnemonic
hpelitebook745G2 Jan 12, 2025
677e7e9
Merge branch 'test' into feat/dart-consumer-auth-provider
hpelitebook745G2 Jan 12, 2025
5c45fd1
fix: updated implementation using encryptedSeed
hpelitebook745G2 Jan 13, 2025
d32b5ba
fix: remove unused code
hpelitebook745G2 Jan 13, 2025
6239574
fix: update implementation to use encryptedSeed
hpelitebook745G2 Jan 13, 2025
ae4c92c
Merge branch 'main' into dart-auth-provider
Jan 13, 2025
ed46c19
fix: move wallet material to constructor
hpelitebook745G2 Jan 14, 2025
65cc92f
fix: rename environment types for consistency
hpelitebook745G2 Jan 14, 2025
42e3181
fix: extract common endpoints
hpelitebook745G2 Jan 14, 2025
6c58a13
fix: rename package to affinidi_tdk_consumer_auth_provider
hpelitebook745G2 Jan 14, 2025
d537ad8
Merge branch 'dart-auth-provider' of https://github.com/affinidi/affi…
hpelitebook745G2 Jan 14, 2025
a7fe172
fix: rename package folder to consumer_auth_provider
hpelitebook745G2 Jan 14, 2025
5e3794f
fix: removed old file
hpelitebook745G2 Jan 14, 2025
783aab3
fix: refactor
Jan 14, 2025
c4304ed
Merge branch 'dart-auth-provider' of https://github.com/affinidi/affi…
hpelitebook745G2 Jan 14, 2025
390864a
fix: rename packages correctly
hpelitebook745G2 Jan 14, 2025
4d278d8
Merge branch 'main' into dart-auth-provider
Jan 15, 2025
ca2de50
feat: dart auth provider tests (#439)
carlos-affinidi Jan 15, 2025
791bdcc
Merge branch 'main' into dart-auth-provider
Jan 15, 2025
84e9a67
fix: add check for existing token
hpelitebook745G2 Jan 16, 2025
c8832e5
Merge branch 'dart-auth-provider' of https://github.com/affinidi/affi…
hpelitebook745G2 Jan 16, 2025
fc91e8a
chore: gitignored fvmrc
hpelitebook745G2 Jan 16, 2025
72331ac
Merge pull request #422 from affinidi/feat/dart-consumer-auth-provider
hpelitebook745G2 Jan 16, 2025
e1e4f9e
feat: add check for expiration
hpelitebook745G2 Jan 16, 2025
6b092e9
Merge pull request #459 from affinidi/feat/FTL-18957-refresh-token
hpelitebook745G2 Jan 16, 2025
4d8d573
fix: env in integration test
Jan 16, 2025
59e8f91
fix: update integration test
Jan 16, 2025
1db33a5
feat: decrypt encrypted seed (#463)
hpelitebook745G2 Jan 16, 2025
9b96272
chore: remove leftover file
Jan 16, 2025
42733ce
feat: add script to generate dart code
hpelitebook745G2 Jan 17, 2025
b7aff41
fix: move decryptSeed into the CryptographyService
hpelitebook745G2 Jan 17, 2025
d958f9a
Merge pull request #469 from affinidi/feat/script-dart-generate
hpelitebook745G2 Jan 17, 2025
60859c0
Merge pull request #470 from affinidi/fix/consumer-decryption
hpelitebook745G2 Jan 17, 2025
bcf7a71
feat: move AesCbcEncryptionService to affinidi_cryptography_service
hpelitebook745G2 Jan 17, 2025
be600e1
chore: dart integration tests (#468)
carlos-affinidi Jan 17, 2025
00861f5
Merge branch 'main' into dart-auth-provider
Jan 17, 2025
7abc94a
fix: refresh token on all verification failures
Jan 17, 2025
ccb606d
Merge pull request #478 from affinidi/feat/FTL-19033-aes-cbc
hpelitebook745G2 Jan 20, 2025
0c59600
feat: add dart docs
hpelitebook745G2 Jan 20, 2025
abb8311
chore: remove API section
hpelitebook745G2 Jan 20, 2025
94caedc
Merge branch 'main' into dart-auth-provider
Jan 20, 2025
ff1cd24
fix: fix Dart code generation
hpelitebook745G2 Jan 20, 2025
a0c0ffd
chore: test signed commit
hpelitebook745G2 Jan 20, 2025
3b983e7
feat: add consumer abstraction
hpelitebook745G2 Jan 21, 2025
90e4958
Merge branch 'dart-auth-provider' of https://github.com/affinidi/affi…
hpelitebook745G2 Jan 21, 2025
4bfcaba
chore: add VDM as example
hpelitebook745G2 Jan 21, 2025
3bffc57
feat: workspace (#488)
carlos-affinidi Jan 21, 2025
80e1ac8
Merge branch 'main' into dart-auth-provider
Jan 21, 2025
0f1a54a
chore: change to TDK
hpelitebook745G2 Jan 21, 2025
c88cbb1
Merge branch 'dart-auth-provider' of https://github.com/affinidi/affi…
hpelitebook745G2 Jan 21, 2025
cb3f9c9
chore: updated package descriptions
hpelitebook745G2 Jan 21, 2025
108dae4
Merge pull request #484 from affinidi/fix/FTL-19073-code-generation
hpelitebook745G2 Jan 21, 2025
d2b9f80
Merge pull request #481 from affinidi/feat/FTL-19002-consumer-docs
hpelitebook745G2 Jan 21, 2025
69853b1
Merge branch 'dart-auth-provider' of https://github.com/affinidi/affi…
hpelitebook745G2 Jan 21, 2025
4864065
chore: move docs from base implementation
hpelitebook745G2 Jan 21, 2025
6cbd59a
fix: initiate tokenProvider from constructor
hpelitebook745G2 Jan 21, 2025
6b8ad0f
Merge pull request #490 from affinidi/feat/FTL-19077-consumer-abstrac…
hpelitebook745G2 Jan 21, 2025
620a013
feat: add CryptographyService abstraction
hpelitebook745G2 Jan 21, 2025
abc42a8
feat: add abstraction, docs, joined cryptography in one service
hpelitebook745G2 Jan 21, 2025
a114d4c
Merge pull request #491 from affinidi/feat/FTL-19078-cryptography-fin…
hpelitebook745G2 Jan 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions packages/dart/affinidi_auth_provider/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Personal access token
PROJECT_ID=""
TOKEN_ID=""
PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"
PASSPHRASE="" # Optional. Required if private key is encrypted
KEY_ID="" # Optional. Required if token's key id is different from token id

# Iota (Websocket)
IOTA_CONFIG_ID=""
DID="" # Usually obtained at runtime from the registered user
11 changes: 11 additions & 0 deletions packages/dart/affinidi_auth_provider/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# https://dart.dev/guides/libraries/private-files
# Created by `dart pub`
.dart_tool/

# Avoid committing pubspec.lock for library packages; see
# https://dart.dev/guides/libraries/private-files#pubspeclock.
pubspec.lock

# env files
.env*
!.env.example
3 changes: 3 additions & 0 deletions packages/dart/affinidi_auth_provider/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 1.0.0

- Initial version.
39 changes: 39 additions & 0 deletions packages/dart/affinidi_auth_provider/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<!--
This README describes the package. If you publish this package to pub.dev,
this README's contents appear on the landing page for your package.

For information about how to write a good package README, see the guide for
[writing package pages](https://dart.dev/guides/libraries/writing-package-pages).

For general information about developing packages, see the Dart guide for
[creating packages](https://dart.dev/guides/libraries/create-library-packages)
and the Flutter guide for
[developing packages and plugins](https://flutter.dev/developing-packages).
-->

TODO: Put a short description of the package here that helps potential users
know whether this package might be useful for them.

## Features

TODO: List what your package can do. Maybe include images, gifs, or videos.

## Getting started

TODO: List prerequisites and provide or point to information on how to
start using the package.

## Usage

TODO: Include short and useful examples for package users. Add longer examples
to `/example` folder.

```dart
const like = 'sample';
```

## Additional information

TODO: Tell users more about the package: where to find more information, how to
contribute to the package, how to file issues, what response they can expect
from the package authors, and more.
30 changes: 30 additions & 0 deletions packages/dart/affinidi_auth_provider/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# This file configures the static analysis results for your project (errors,
# warnings, and lints).
#
# This enables the 'recommended' set of lints from `package:lints`.
# This set helps identify many issues that may lead to problems when running
# or consuming Dart code, and enforces writing Dart using a single, idiomatic
# style and format.
#
# If you want a smaller set of lints you can change this to specify
# 'package:lints/core.yaml'. These are just the most critical lints
# (the recommended set includes the core lints).
# The core lints are also what is used by pub.dev for scoring packages.

include: package:lints/recommended.yaml

# Uncomment the following section to specify additional rules.

# linter:
# rules:
# - camel_case_types

# analyzer:
# exclude:
# - path/to/excluded/files/**

# For more information about the core and recommended set of lints, see
# https://dart.dev/go/core-lints

# For additional information about configuring this file, see
# https://dart.dev/guides/language/analysis-options
33 changes: 33 additions & 0 deletions packages/dart/affinidi_auth_provider/example/iota_token.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import 'package:affinidi_auth_provider/affinidi_auth_provider.dart';
import 'package:dotenv/dotenv.dart';

void main() async {
var env = DotEnv()..load();
if (!env.isEveryDefined(
['PROJECT_ID', 'TOKEN_ID', 'PRIVATE_KEY', 'IOTA_CONFIG_ID', 'DID'])) {
print(
'Missing environment variables. Please provide PROJECT_ID, TOKEN_ID, PRIVATE_KEY, DID');
return;
}
// Workaround for dotenv multiline limitations
final privateKey = env['PRIVATE_KEY']!.replaceAll('\\n', '\n');

final provider = AuthProvider(
projectId: env['PROJECT_ID']!,
tokenId: env['TOKEN_ID']!,
privateKey: privateKey,
// Optional parameters
keyId: env['KEY_ID'],
passphrase: env['PASSPHRASE'],
);

try {
// Fetch iota token (websocket). Did is usually obtained at runtime from the registered user
final iotaToken = provider.createIotaToken(
iotaConfigId: env['IOTA_CONFIG_ID']!, did: env['DID']!);
print('Successfully obtained iota token:');
print(iotaToken);
} catch (e) {
print('Error obtaining token: $e');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import 'package:affinidi_auth_provider/affinidi_auth_provider.dart';
import 'package:dotenv/dotenv.dart';

void main() async {
final env = DotEnv(includePlatformEnvironment: true)..load();
if (!env.isEveryDefined(['PROJECT_ID', 'TOKEN_ID', 'PRIVATE_KEY'])) {
print(
'Missing environment variables. Please provide PROJECT_ID, TOKEN_ID, PRIVATE_KEY');
return;
}
// Workaround for dotenv multiline limitations
final privateKey = env['PRIVATE_KEY']!.replaceAll('\\n', '\n');

final provider = AuthProvider(
projectId: env['PROJECT_ID']!,
tokenId: env['TOKEN_ID']!,
privateKey: privateKey,
// Optional parameters
keyId: env['KEY_ID'],
passphrase: env['PASSPHRASE'],
);

try {
// Fetch project scoped token
final projectScopedToken = await provider.fetchProjectScopedToken();
print('Successfully obtained project scoped token:');
print(projectScopedToken);
} catch (e) {
print('Error obtaining token: $e');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/// Support for doing something awesome.
///
/// More dartdocs go here.
library;

export 'src/auth_provider.dart';

// TODO: Export any libraries intended for clients of this package.
136 changes: 136 additions & 0 deletions packages/dart/affinidi_auth_provider/lib/src/auth_provider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import 'dart:convert';

import 'package:dart_jsonwebtoken/dart_jsonwebtoken.dart';
import 'package:affinidi_auth_provider/src/jwt_helper.dart';
import 'package:affinidi_common/affinidi_common.dart';
import 'package:http/http.dart' as http;
import 'package:uuid/uuid.dart';

class AuthProvider {
final String projectId;
final String tokenId;
final String privateKey;
final String? keyId;
final String? passphrase;
final String apiGatewayUrl;
final String tokenEndpoint;

AuthProvider(
{required this.projectId,
required this.tokenId,
required this.privateKey,
this.keyId,
this.passphrase})
: apiGatewayUrl = Environment.fetchApiGwUrl(),
tokenEndpoint = Environment.fetchElementsAuthTokenUrl();

AuthProvider.withEnv(
{required this.projectId,
required this.tokenId,
required this.privateKey,
this.keyId,
this.passphrase,
required this.apiGatewayUrl,
required this.tokenEndpoint});

ECPublicKey? publicKey;
String? projectScopedToken;

Future<bool> _shouldFetchToken() async {
if (projectScopedToken == null) {
return true;
}
publicKey ??= await JWTHelper.fetchPublicKey(apiGatewayUrl);
try {
JWT.verify(projectScopedToken!, publicKey!);
return false;
} on JWTExpiredException {
return true;
}
}

Future<String> fetchProjectScopedToken() async {
if (await _shouldFetchToken()) {
projectScopedToken =
await _getProjectScopedToken(audience: tokenEndpoint);
}
return projectScopedToken!;
}

Future<String> _getUserAccessToken({required String audience}) async {
final token = JWTHelper.signPayload(
audience: audience,
tokenId: tokenId,
privateKey: privateKey,
keyId: keyId,
passphrase: passphrase,
);

final response = await http.post(
Uri.parse(audience),
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: {
'grant_type': 'client_credentials',
'scope': 'openid',
'client_assertion_type':
'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
'client_assertion': token,
'client_id': tokenId,
},
);

if (response.statusCode != 200) {
throw Exception('Failed to get user access token');
}

final data = jsonDecode(response.body);
return data['access_token'];
}

Future<String> _getProjectScopedToken({
required String audience,
}) async {
final userAccessToken = await _getUserAccessToken(audience: audience);

final response = await http.post(
Uri.parse('$apiGatewayUrl/iam/v1/sts/create-project-scoped-token'),
headers: {
'Authorization': 'Bearer $userAccessToken',
'Content-Type': 'application/json',
},
body: jsonEncode({'projectId': projectId}),
);

if (response.statusCode != 200) {
throw Exception('Failed to get project scoped token');
}

final data = jsonDecode(response.body);
return data['accessToken'];
}

({String iotaJwt, String iotaSessionId}) createIotaToken({
required String iotaConfigId,
required String did,
String? iotaSessionId,
}) {
final sessionId = iotaSessionId ?? Uuid().v4();

return (
iotaJwt: JWTHelper.signPayload(
audience: did,
tokenId: 'token/$tokenId',
privateKey: privateKey,
keyId: keyId,
passphrase: passphrase,
additionalPayload: {
'project_id': projectId,
'iota_configuration_id': iotaConfigId,
'iota_session_id': iotaSessionId,
'scope': 'iota_channel',
},
),
iotaSessionId: sessionId,
);
}
}
Loading
Loading