Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,29 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.1.2-beta] - 2025-08-15

### Added
- **MiAuth authentication support** - Alternative authentication method for Misskey servers
- **Comprehensive error handling system** - Granular exception classes for different error scenarios

### Changed
- **Error handling architecture** - Replaced generic exceptions with specific `MisskeyAuthException` subclasses
- **OAuth client improvements** - Enhanced error mapping and better exception handling
- **MiAuth client implementation** - Complete MiAuth authentication flow with proper error handling

### Features
- `MisskeyMiAuthClient` - Main MiAuth authentication client
- `MisskeyMiAuthConfig` - Configuration class for MiAuth authentication
- `MiAuthTokenResponse` - Response model for MiAuth authentication
- Enhanced exception classes including:
- `OAuthNotSupportedException` - Server doesn't support OAuth 2.0
- `MiAuthDeniedException` - User denied MiAuth permission
- `NetworkException` - Network connectivity issues
- `UserCancelledException` - User cancelled authentication
- `CallbackSchemeErrorException` - URL scheme configuration errors
- And 15+ more specific exception classes

## [0.1.1-beta] - 2025-08-12

### Changed
Expand Down
208 changes: 188 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Add this to your package's `pubspec.yaml` file:

```yaml
dependencies:
misskey_auth: ^0.1.1-beta
misskey_auth: ^0.1.2-beta
```

### Quick Start
Expand Down Expand Up @@ -134,6 +134,63 @@ Add to `android/app/src/main/AndroidManifest.xml`:
</activity>
```

#### Differences in MiAuth and OAuth Configuration (Key Points for App Integration)
- This configuration (registration of the URL scheme) is done on the "app side." It is not included in the library's Manifest.
- Both methods require a "custom URL scheme" to return from an external browser to the app.
- The difference lies in how to specify "where to return from the browser."
- OAuth: Since it needs to return to an HTTPS `redirect_uri` from the authorization server, `redirect.html` placed there ultimately redirects back to `yourscheme://...` for the app.
- MiAuth: The `callback` query of the authentication start URL specifies `yourscheme://...` from the beginning (no need for `https`).

##### Example of MiAuth

```dart
import 'package:misskey_auth/misskey_auth.dart';

final miClient = MisskeyMiAuthClient();
final miConfig = MisskeyMiAuthConfig(
host: 'misskey.io',
appName: 'Your App',
callbackScheme: 'yourscheme', // Scheme registered on the app side
permissions: ['read:account', 'write:notes'],
iconUrl: 'https://example.com/icon.png', // Optional
);
final miRes = await miClient.authenticate(miConfig);
```

##### Example of OAuth

```dart
import 'package:misskey_auth/misskey_auth.dart';

final oauthClient = MisskeyOAuthClient();
final oauthConfig = MisskeyOAuthConfig(
host: 'misskey.io',
clientId: 'https://yourpage/yourapp/',
redirectUri: 'https://yourpage/yourapp/redirect.html',
scope: 'read:account write:notes',
callbackScheme: 'yourscheme', // Scheme registered on the app side
);
final token = await oauthClient.authenticate(oauthConfig);
```

##### How to Support Both Methods in the Same App
- By registering the same `scheme` (e.g., `yourscheme`) in iOS's `Info.plist` and Android's `AndroidManifest.xml`, it can be shared between OAuth and MiAuth.
- If you implement the OAuth `redirect.html` to redirect to `yourscheme://oauth/callback?...`, you can reuse the same path expression (`yourscheme://oauth/callback`) for MiAuth's `callback`.
- For Android, matching only on the `scheme` is sufficient as shown below (the `host` and `path` are optional).

```xml
<activity android:name="com.linusu.flutter_web_auth.CallbackActivity" android:exported="true">
<intent-filter android:label="flutter_web_auth">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="yourscheme" />
</intent-filter>
<!-- Add this only if you want to restrict by host/path -->
<!-- <intent-filter> ... <data android:scheme="yourscheme" android:host="oauth" android:path="/callback"/> ... </intent-filter> -->
</activity>
```

### API Reference

#### MisskeyOAuthConfig
Expand All @@ -152,26 +209,52 @@ class MisskeyOAuthConfig {

#### MisskeyOAuthClient

Main client for handling Misskey authentication.
Main client for handling Misskey OAuth authentication.

```dart
class MisskeyOAuthClient {
/// Authenticate with Misskey server
Future<OAuthTokenResponse> authenticate(MisskeyOAuthConfig config);
Future<OAuthTokenResponse?> authenticate(MisskeyOAuthConfig config);

/// Get OAuth server information
Future<OAuthServerInfo?> getOAuthServerInfo(String host);

/// Check if server supports OAuth 2.0
Future<bool> isOAuthSupported(String host);
/// Get stored access token
Future<String?> getStoredAccessToken();

/// Clear stored tokens
Future<void> clearTokens();
}
```

#### MisskeyMiAuthClient

Main client for handling Misskey MiAuth authentication.

```dart
class MisskeyMiAuthClient {
/// Authenticate with Misskey server using MiAuth
Future<MiAuthTokenResponse> authenticate(MisskeyMiAuthConfig config);

/// Get stored access token
Future<String?> getStoredAccessToken();

/// Clear stored tokens
Future<void> clearTokens();
}
```

### Error Handling

The library provides custom exceptions for different error scenarios:
The library provides comprehensive error handling with custom exception classes for different scenarios. For detailed information about each exception class and their usage, please refer to the documentation on pub.dev.

- `MisskeyAuthException` - Base exception class
- `OAuthNotSupportedException` - When server doesn't support OAuth 2.0
- `AuthenticationFailedException` - When authentication fails
- `TokenExchangeException` - When token exchange fails
The library includes exception classes for:
- Authentication configuration errors
- Network and connectivity issues
- OAuth and MiAuth specific errors
- User cancellation and authorization failures
- Secure storage operations
- Response parsing errors

### Common Errors

Expand Down Expand Up @@ -251,7 +334,7 @@ MisskeyのOAuth認証・MiAuth認証をFlutterアプリで簡単に扱うため

```yaml
dependencies:
misskey_auth: ^0.1.1-beta
misskey_auth: ^0.1.2-beta
```

### クイックスタート
Expand Down Expand Up @@ -355,6 +438,65 @@ final token = await client.authenticate(config);
</activity>
```

#### MiAuth と OAuth の設定の違い(アプリ組み込み時のポイント)

- この設定(URLスキームの登録)は「アプリ側」で行います。ライブラリ内のManifestには含めません。
- 両方式とも、外部ブラウザからアプリへ戻すために「カスタムURLスキーム」が必要です。
- 相違点は「ブラウザからどこに戻すか」の指定方法です。
- OAuth: 認可サーバーからはHTTPSの`redirect_uri`に戻る必要があるため、そこに配置した`redirect.html`が最終的に`yourscheme://...`へリダイレクトしてアプリに戻します。
- MiAuth: 認証開始URLの`callback`クエリに、最初から`yourscheme://...`を指定します(`https`は不要)。

##### MiAuth の例(Dart)

```dart
import 'package:misskey_auth/misskey_auth.dart';

final miClient = MisskeyMiAuthClient();
final miConfig = MisskeyMiAuthConfig(
host: 'misskey.io',
appName: 'Your App',
callbackScheme: 'yourscheme', // アプリ側で登録したスキーム
permissions: ['read:account', 'write:notes'],
iconUrl: 'https://example.com/icon.png', // 任意
);
final miRes = await miClient.authenticate(miConfig);
```

##### OAuth の例

```dart
import 'package:misskey_auth/misskey_auth.dart';

final oauthClient = MisskeyOAuthClient();
final oauthConfig = MisskeyOAuthConfig(
host: 'misskey.io',
clientId: 'https://yourpage/yourapp/',
redirectUri: 'https://yourpage/yourapp/redirect.html',
scope: 'read:account write:notes',
callbackScheme: 'yourscheme', // アプリ側で登録したスキーム
);
final token = await oauthClient.authenticate(oauthConfig);
```

##### 両方式を同一アプリでサポートするには

- iOSの`Info.plist`・Androidの`AndroidManifest.xml`で同じ`sheme`(例: `yourscheme`)を1つ登録すれば、OAuth/MiAuthで共用可能です。
- OAuth用の`redirect.html`は、`yourscheme://oauth/callback?...`へ飛ばす実装にしておくと、MiAuthの`callback`でも同じパス表現(`yourscheme://oauth/callback`)を使い回せます。
- Androidは以下のように`scheme`のみのマッチで十分です(`host`や`path`は任意)。

```xml
<activity android:name="com.linusu.flutter_web_auth.CallbackActivity" android:exported="true">
<intent-filter android:label="flutter_web_auth">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="yourscheme" />
</intent-filter>
<!-- 必要に応じて、host/pathで限定したい場合のみ追記 -->
<!-- <intent-filter> ... <data android:scheme="yourscheme" android:host="oauth" android:path="/callback"/> ... </intent-filter> -->
</activity>
```

### API リファレンス

#### MisskeyOAuthConfig
Expand All @@ -373,26 +515,52 @@ class MisskeyOAuthConfig {

#### MisskeyOAuthClient

Misskey認証を処理するメインクライアント。
Misskey OAuth認証を処理するメインクラス

```dart
class MisskeyOAuthClient {
/// Misskeyサーバーで認証を実行
Future<OAuthTokenResponse> authenticate(MisskeyOAuthConfig config);
Future<OAuthTokenResponse?> authenticate(MisskeyOAuthConfig config);

/// OAuthサーバー情報を取得
Future<OAuthServerInfo?> getOAuthServerInfo(String host);

/// 保存されたアクセストークンを取得
Future<String?> getStoredAccessToken();

/// 保存されたトークンを削除
Future<void> clearTokens();
}
```

#### MisskeyMiAuthClient

Misskey MiAuth認証を処理するメインクラス

```dart
class MisskeyMiAuthClient {
/// MisskeyサーバーでMiAuth認証を実行
Future<MiAuthTokenResponse> authenticate(MisskeyMiAuthConfig config);

/// 保存されたアクセストークンを取得
Future<String?> getStoredAccessToken();

/// サーバーがOAuth 2.0をサポートしているかチェック
Future<bool> isOAuthSupported(String host);
/// 保存されたトークンを削除
Future<void> clearTokens();
}
```

### エラーハンドリング

ライブラリは様々なエラーシナリオに対応するカスタム例外を提供します:
ライブラリには以下のカテゴリの例外クラスが含まれています:
- 認証設定エラー
- ネットワーク・接続エラー
- OAuth・MiAuth固有のエラー
- ユーザーキャンセル・認可失敗
- セキュアストレージ操作エラー
- レスポンス解析エラー

- `MisskeyAuthException` - ベース例外クラス
- `OAuthNotSupportedException` - サーバーがOAuth 2.0をサポートしていない場合
- `AuthenticationFailedException` - 認証が失敗した場合
- `TokenExchangeException` - トークン交換が失敗した場合
詳細についてはpub.devのドキュメントを参考にして下さい

### よくあるエラー

Expand Down
8 changes: 0 additions & 8 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,6 @@
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>

<!-- OAuth redirect handling -->
<intent-filter android:label="flutter_web_auth_2">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="misskeyauth" android:host="oauth" android:path="/callback" />
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
Expand Down
11 changes: 11 additions & 0 deletions example/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,17 @@
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>

<!-- flutter_web_auth_2 用のコールバック受け取り Activity -->
<activity android:name="com.linusu.flutter_web_auth.CallbackActivity" android:exported="true">
<intent-filter android:label="flutter_web_auth_2">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- 例のコールバックスキーム。必要に応じて変更 -->
<data android:scheme="misskeyauth" />
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
Expand Down
Loading
Loading