{"id":29745596,"url":"https://github.com/fa-fifi/keycloak_wrapper","last_synced_at":"2025-07-26T06:15:21.074Z","repository":{"id":194745912,"uuid":"691480872","full_name":"fa-fifi/keycloak_wrapper","owner":"fa-fifi","description":"Keycloak Single Sign-On (SSO) authentication package for Flutter framework.","archived":false,"fork":false,"pushed_at":"2025-07-22T06:01:16.000Z","size":284,"stargazers_count":17,"open_issues_count":5,"forks_count":15,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-07-22T08:34:46.221Z","etag":null,"topics":["android","ios","macos"],"latest_commit_sha":null,"homepage":"https://pub.dev/packages/keycloak_wrapper","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fa-fifi.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-09-14T09:08:30.000Z","updated_at":"2025-07-06T15:28:00.000Z","dependencies_parsed_at":"2023-10-04T09:08:21.723Z","dependency_job_id":"fa7d72dc-a8eb-4358-950a-ffb802bb57e1","html_url":"https://github.com/fa-fifi/keycloak_wrapper","commit_stats":null,"previous_names":["fa-fifi/keycloak-wrapper","fa-fifi/keycloak_wrapper"],"tags_count":22,"template":false,"template_full_name":null,"purl":"pkg:github/fa-fifi/keycloak_wrapper","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fa-fifi%2Fkeycloak_wrapper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fa-fifi%2Fkeycloak_wrapper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fa-fifi%2Fkeycloak_wrapper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fa-fifi%2Fkeycloak_wrapper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fa-fifi","download_url":"https://codeload.github.com/fa-fifi/keycloak_wrapper/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fa-fifi%2Fkeycloak_wrapper/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267127972,"owners_count":24040154,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-26T02:00:08.937Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","ios","macos"],"created_at":"2025-07-26T06:15:17.960Z","updated_at":"2025-07-26T06:15:21.051Z","avatar_url":"https://github.com/fa-fifi.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Keycloak Wrapper\n[![pub package](https://img.shields.io/pub/v/keycloak_wrapper.svg)](https://pub.dartlang.org/packages/keycloak_wrapper)\n[![likes](https://img.shields.io/pub/likes/keycloak_wrapper)](https://pub.dev/packages/keycloak_wrapper/score)\n[![pub points](https://img.shields.io/pub/points/keycloak_wrapper)](https://pub.dev/packages/keycloak_wrapper/score)\n[![downloads](https://img.shields.io/pub/dm/keycloak_wrapper)](https://pub.dev/packages/keycloak_wrapper/score)\n[![style: lint](https://img.shields.io/badge/style-lint-4BC0F5.svg)](https://pub.dev/packages/lint)\n[![StandWithPalestine](https://raw.githubusercontent.com/TheBSD/StandWithPalestine/main/badges/StandWithPalestine.svg)](https://github.com/TheBSD/StandWithPalestine/blob/main/docs/README.md)\n\n\u003cbr/\u003e\u003ca href=\"https://www.keycloak.org\"\u003e\u003cimg src=\"https://www.keycloak.org/resources/images/logo.svg\" width=\"100%\" alt=\"cover image\" url=\"https://www.keycloak.org\"/\u003e\u003c/a\u003e\u003cbr/\u003e\n\nIntegrate **Keycloak Single Sign-On (SSO)** authentication into your Flutter apps seamlessly using this package. Tokens are automatically managed under the hood and are easily accessible. A user authentication state stream is provided for your app to listen to in order to stay in sync with authentication status changes.\n\n## Getting Started\n\nFor end-user authentication and authorization, this package integrates with the [**AppAuth**](https://appauth.io) SDK to establish connections using [**OAuth 2.0**](https://datatracker.ietf.org/doc/html/rfc6749) and [**OpenID Connect (OIDC)**](https://openid.net/specs/openid-connect-core-1_0.html). This integration allows users to securely log in and access protected resources, such as APIs or user data from third-party providers. For token security, the [**flutter_secure_storage**](https://pub.dev/packages/flutter_secure_storage) package is used to securely store all tokens in the Keychain for iOS and Keystore for Android.\n\n\u003e [!NOTE]\n\u003e - [**AndroidX**](https://developer.android.com/jetpack/androidx) is required for this package. Starting from Flutter v1.12.13, newly created projects enable AndroidX by default. If your project was created before this Flutter version, please migrate it before using this package. You can follow this migration [guide](https://docs.flutter.dev/release/breaking-changes/androidx-migration) provided by the Flutter team.\n\u003e\n\u003e - Starting with Android API 28 and iOS 9, insecure HTTP connections are disabled by default. Check out this [guide](https://docs.flutter.dev/release/breaking-changes/network-policy-ios-android) if you want to allow cleartext connections for your build. However, it is not recommended for release builds. Please use secure connections whenever possible.\n\n### **Keycloak**\nGo to your **Keycloak Administration Console** and select your Client ID. In the access settings section, add `\u003cbundle_identifier\u003e:/*` as a **valid redirect URI**, and do the same for the **valid post logout redirect URI**. Ensure your bundle identifier does not contain any characters that are not allowed in a hostname, such as spaces or underscores.\n\n### **Android**\nSpecify the custom scheme in your Android app’s `build.gradle` file. There should be a section similar to the following; replace `\u003cpackage_name\u003e` with your desired value:\n\n```groovy\nandroid {\n    ...\n    defaultConfig {\n        ...\n        manifestPlaceholders += [\n                'appAuthRedirectScheme': '\u003cpackage_name\u003e'\n        ]\n    }\n}\n```\n\nEnsure that `\u003cpackage_name\u003e` is all lowercase, as there have been reports of issues with redirects if there are any capital letters. Note that the `+=` operation is used on `manifestPlaceholders` instead of `=`. This is intentional and required, as newer versions of the Flutter SDK have made changes under the hood to handle multidex. Using `=` instead of `+=` can lead to errors like the following:\n\n```\nAttribute application@name at AndroidManifest.xml:5:9-42 requires a placeholder substitution but no value for \u003capplicationName\u003e is provided.\n```\n\nIf you see this error, update your `build.gradle` to use `+=` instead.\n\n\u003e [!WARNING]\n\u003e - Starting from Flutter v3.22.0, newly created projects will disallow [task affinity](https://github.com/flutter/flutter/pull/144018) by default to prevent the [StrandHogg attack](https://developer.android.com/privacy-and-security/risks/strandhogg). However, these changes have broken the package, as users will no longer be able to redirect back to the app after login. Currently, the only way to fix this issue is to remove `android:taskAffinity=\"\"` from your `AndroidManifest.xml` file.\n\n### **iOS/macOS**\nSpecify the custom scheme in your iOS/macOS app’s `Info.plist` file. There should be a section similar to the following; replace `\u003cbundle_identifier\u003e` with your desired value:\n\n```xml\n\u003ckey\u003eCFBundleURLTypes\u003c/key\u003e\n\u003carray\u003e\n    \u003cdict\u003e\n        \u003ckey\u003eCFBundleTypeRole\u003c/key\u003e\n        \u003cstring\u003eEditor\u003c/string\u003e\n        \u003ckey\u003eCFBundleURLSchemes\u003c/key\u003e\n        \u003carray\u003e\n            \u003cstring\u003e\u003cbundle_identifier\u003e\u003c/string\u003e\n        \u003c/array\u003e\n    \u003c/dict\u003e\n\u003c/array\u003e\n```\n\n## Usage\nCreate an instance of the `KeycloakWrapper` class somewhere in your code, as shown below. Make sure to replace all placeholders with your own configuration values.\n\n```dart\nfinal keycloakConfig = KeycloakConfig(\n  bundleIdentifier: '\u003cbundle_identifier\u003e',\n  clientId: '\u003cclient_id\u003e',\n  frontendUrl: '\u003cfrontend_url\u003e',\n  realm: '\u003crealm\u003e',\n);\n\nfinal keycloakWrapper = KeycloakWrapper(config: keycloakConfig);\n```\n\nInitialize the package within the `main()` method of your Flutter app to set up the user authentication stream as soon as your app launches.\n\n```dart\nvoid main() {\n  WidgetsFlutterBinding.ensureInitialized();\n  keycloakWrapper.initialize();\n  ...\n  runApp(const MyApp());\n}\n```\n\nTo listen to the user authentication state stream, create a StreamBuilder widget that listens to `keycloakWrapper.authenticationStream`. Navigate the user to the login screen when the stream returns false, and redirect to the home screen when login is successful. Set the initial value of the StreamBuilder to `false` to ensure the stream never returns null.\n\n```dart\nclass MyApp extends StatelessWidget {\n  const MyApp({super.key});\n\n  @override\n  Widget build(BuildContext context) =\u003e MaterialApp(\n        home: StreamBuilder\u003cbool\u003e(\n            initialData: false,\n            stream: keycloakWrapper.authenticationStream,\n            builder: (context, snapshot) =\u003e\n                snapshot.data! ? const HomeScreen() : const LoginScreen()),\n      );\n}\n```\n\nNext, create a button somewhere in your login screen and use the following method to initiate the login process:\n\n```dart\nFuture\u003cvoid\u003e login() async {\n  final isLoggedIn = await keycloakWrapper.login();\n}\n```\n\nOnce logged in, you can retrieve the user's information and tokens as shown below:\n\n```dart\n// Retrieve user's information.\nfinal user = await keycloakWrapper.getUserInfo();\n\nfinal name = user?['name'];\nfinal email = user?['email'];\n\n// Retrieve tokens.\nfinal accessToken = keycloakWrapper.accessToken;\nfinal idToken = keycloakWrapper.idToken;\nfinal refreshToken = keycloakWrapper.refreshToken;\n```\n\nTo log out, simply call the following method. Make sure to pop all stacked screens, if there are any.\n\n```dart\nFuture\u003cvoid\u003e logout() async {\n  final isLoggedOut = await keycloakWrapper.logout();\n}\n```\n\nBy default, all errors and exceptions are handled by the `onError` method of the `KeycloakWrapper` class, which prints the error directly to the console. You can customize this behavior if you want to display a custom message to users when specific errors, such as authorization failures, occur. Below is an example of how you can override the method and handle errors and exceptions in your own way:\n\n```dart\nkeycloakWrapper.onError = (message, error, stackTrace) {\n  // Add your custom error handling logic here.\n};\n```\n\nYou can refer to the [example](https://pub.dev/packages/keycloak_wrapper/example) to see how this package works in a real-life app.\n\n## Contributing\n\nContributions are welcome! However, please make sure to follow the guidelines below to avoid unnecessary waste of time and resources.\n\n- **Found a bug?**  \n  Ensure the bug has not already been reported by searching on GitHub under [Issues](https://github.com/fa-fifi/keycloak_wrapper/issues). If you can't find an open issue addressing the problem, open a new one. Be sure to include a title, a clear description, as much relevant information as possible, and a code sample or an executable test case demonstrating the expected behavior that is not occurring.\n\n- **Need some help?**  \n  Feel free to open a new [discussion](https://github.com/fa-fifi/keycloak_wrapper/discussions) on GitHub if you need help from the community. I'll try my best to help you as soon as possible. If you want to make any feature requests, you can use the same platform for us to discuss your idea further.\n\n- **Want to contribute?**  \n  Since I am the only maintainer of this package, frequent bug fixes or updates might not be feasible. Therefore, any [pull requests](https://github.com/fa-fifi/keycloak_wrapper/pulls) are greatly appreciated! Please ensure that the PR description clearly outlines both the problem and the proposed solution. If applicable, include the relevant issue number in the description.\n\nThanks! ❤️","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffa-fifi%2Fkeycloak_wrapper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffa-fifi%2Fkeycloak_wrapper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffa-fifi%2Fkeycloak_wrapper/lists"}