Skip to content

Conversation

@kkalass
Copy link

@kkalass kkalass commented Aug 3, 2025

Thanks a lot for your groundwork on supporting solid OIDC on Flutter! Like we discussed per email and Signal, I looked into updating the project to make use of the oidc package. I am sorry that it ended up to be such a huge API change, but on the upside this brings some additional features like session restoration. I hope you are fine with this.

🚀 Overview

This PR migrates the solid_auth library from its embedded copy of openid_client to the modern oidc package, primarily to gain RFC 8252 (OAuth 2.0 for Native Apps) compliance, while also addressing security vulnerabilities and significantly improving the developer experience.

✨ Key Improvements

🔒 Security Enhancements

  • RFC 8252 Compliance: Migrated to oidc library which implements RFC 8252 (OAuth 2.0 for Native Apps) security best practices
  • Modern Dependencies: Replaced embedded copy of openid_client with actively maintained oidc v0.12.1+2
  • Native App Security: OIDC provides PKCE (Proof Key for Code Exchange) implementation and secure redirect handling
  • DPoP Token Integration: Preserved existing DPoP (Demonstration of Proof-of-Possession) token implementation with simplified API
  • Secure Token Storage: Platform-appropriate secure storage mechanisms
  • WebID Validation: WebID validation by fetching profile documents and verifying identity providers

📱 New Developer Experience Features

  • Reactive State Management: New ValueListenable-based authentication state updates for reactive UI
  • Automatic Session Restoration: Persistent authentication across app restarts with secure parameter storage
  • Simplified API: New class-based SolidAuth API replacing function-based approach
  • Cross-Platform Support: Support for web, mobile (iOS/Android), and desktop (macOS)

📚 Comprehensive Documentation

  • Updated README: Expanded documentation with step-by-step quick start guide, comprehensive examples, and security best practices
  • API Documentation: Extensive inline documentation for all public APIs with practical examples
  • Configuration Guide: Detailed client-profile.jsonld setup instructions with hosting guidance
  • Platform Setup: Clear references to authoritative OIDC setup documentation
  • Security Guidelines: Prominent security considerations and best practices

🔄 Breaking Changes

API Changes

  • Constructor: SolidAuth() constructor replaces previous function-based API
  • Authentication: authenticate() method with reactive state management
  • DPoP Tokens: genDpopToken() with simplified signature
  • Session Management: New init(), logout(), and dispose() lifecycle methods

Configuration Changes

  • Client Profile: Created client-profile.jsonld configuration
  • Redirect URIs: Automatic platform-based redirect URI construction
  • Required Scopes: Explicit documentation of mandatory scopes (openid, webid, offline_access)

📋 Migration Guide

Before (Previous API)

// Previous function-based approach
String issuer = await getIssuer(webId);
var authData = await authenticate(Uri.parse(issuer), scopes);
String dPopToken = genDpopToken(url, keyPair, publicKeyJwk, method);

After (New API)

// New class-based approach with reactive state
final solidAuth = SolidAuth(
  oidcClientId: 'https://myapp.com/client-profile.jsonld',
  appUrlScheme: 'com.mycompany.myapp',
  frontendRedirectUrl: Uri.parse('https://myapp.com/auth/callback.html'),
);

await solidAuth.init();

// Reactive UI updates
ValueListenableBuilder<bool>(
  valueListenable: solidAuth.isAuthenticatedNotifier,
  builder: (context, isAuthenticated, child) => 
    isAuthenticated ? AuthenticatedView() : LoginView(),
);

// Simplified authentication
final result = await solidAuth.authenticate(webId);

// Simplified DPoP tokens
final dpop = solidAuth.genDpopToken(url, 'GET');

🧪 Testing

  • Example App Updated: Complete migration of example application demonstrating all new features
  • Cross-Platform Testing: Verified on web and macOS
  • Security Testing: Validated DPoP token generation and secure storage
  • Session Persistence: Confirmed automatic session restoration works correctly

📦 Dependencies

Added

  • oidc: ^0.12.1+2 - Modern, maintained OpenID Connect library
  • oidc_default_store: ^0.2.1 - Secure token storage implementation

Removed

  • Embedded openid_client code - Replaced with maintained external dependency
  • Previous authentication manager implementations

Preserved

  • dart_jsonwebtoken - Still embedded

🔗 Documentation Improvements

  • Quick Start Guide: Step-by-step numbered instructions with practical examples
  • Hosting Guidance: GitHub Pages, Netlify, Vercel hosting tips for client-profile.jsonld
  • Security Warnings: Prominent alerts about HTTPS requirements and URL matching
  • Platform Setup: References to authoritative OIDC getting started documentation
  • Comprehensive Examples: Authentication with scopes, session management, API requests

🚦 Deployment

  • GitHub Pages: Updated deployment workflow for example application
  • Client Profile: Created example client-profile.jsonld with proper configuration
  • Redirect Handling: New redirect.html using official OIDC package patterns

🎯 Limitations / Future Considerations

There are some topics not addressed in this PR that we probably want to look at in the future:

  • Offline-First Support: Currently need to be online during init()
  • Windows/Linux Support: Both platforms might not work (well) with this solution
  • Structured Error Types: Might be nice

Note: This migration updates the authentication stack to use RFC 8252 compliant dependencies. The new API provides reactive state management and comprehensive documentation. Breaking changes enable RFC 8252 compliance and establish a foundation for future development.

kkalass added 3 commits August 3, 2025 20:57
This PR migrates the authentication system from the custom OpenID Connect
implementation to the well-maintained oidc library, addressing several
security and maintainability concerns.

Key changes:
- Replace custom OpenID client with oidc library for better security
- Add reactive authentication state management with ValueNotifier
- Implement proper DPoP token handling through oidc hooks
- Refactor example app to demonstrate new authentication patterns
- Add client-profile.jsonld for Solid OIDC compliance
- Update dependencies and remove unnused packages

Breaking changes:
- New SolidAuth class replaces previous authenticate() function
- Authentication state is now reactive via isAuthenticatedNotifier
- DPoP token generation integrated into authentication flow

This migration improves security, reduces maintenance burden, and provides
a more modern Flutter-friendly API while maintaining full Solid OIDC
compatibility. The changes have been tested with the example application.

Resolves authentication reliability issues and provides a foundation for
future enhancements to the library.
dart pub add solid_auth
```

### 2. Create Your Client Profile
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think we should discuss the options available in general for OIDC client identification (like preregistering and dynamic registration) and why only the client profile approach is suitable for flutter solid apps? Maybe as a separate markdown document?


---

## Roadmap
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should rather call this section "Limitations"

---

## Roadmap

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And do you think we should also discuss here that the solid specifications for authorizing applications are still in the works and once authorization flow like in https://solid.github.io/data-interoperability-panel/specification/ is available in Solid Server implementations, we want to support it? Currently usually the pod servers give an authenticated application (like our example) full access to the entire pod - I think that it would be valuable for users of solid_auth to be aware of this and that it is a problem in the solid ecosystem on which people are working.

**Future Goal**: Enable fully offline-first applications that can start and function without network connectivity, using cached authentication data and provider configurations.

This is essential for truly offline-capable Solid applications, but requires careful consideration of security trade-offs and cache management strategies.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw, that there currently is another limitation: apparently, token refresh is not fully working. Leaving the tab of my solid_task app open, after some time (an hour or so) I saw synchronization errors due to the access token not being available. Starting the app today shows me that I am logged out again - so the persistence of the login data seems to be limited. Do you think we should document this here?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found the reason - I have to send a certain promt, which I now do. So this is now fixed.

@kkalass
Copy link
Author

kkalass commented Aug 6, 2025

Another thought I had: If you prefer to be able to switch between the old solid-oidc implementation and the new, bdaya-dev/oidc based one, I could revert the part where I delete the embedded code, convert SolidAuth to be an abstract class with factory constructors and provide an implementation of this interface based on the original code base, as well as one based on the new one. So you could switch projects to the new API without changing the underlying implementation first, and then update to the new implementation in a second step.

kkalass and others added 5 commits August 6, 2025 13:46
… offline_access

Previously, Solid OIDC authentication failed to obtain refresh tokens because
the required 'consent' prompt wasn't sent to identity providers. This change
automatically adds the consent prompt when offline_access is in the requested
scopes, enabling proper token refresh and persistent authentication.

Includes configurable prompt calculation and comprehensive test coverage.
- Change default value of strictJwtVerification from false to true
- Update documentation to reflect security-first approach
- Add security warnings for disabling strict verification
- Remove redundant examples showing explicit true value
During refresh, apparently we do not have headers on the request, so we need to set it to an empty map
Added required network permissions documentation to README:
- Android: INTERNET permission in AndroidManifest.xml
- macOS: com.apple.security.network.client entitlement

These permissions are essential for Solid authentication to work
properly when connecting to identity providers and pod servers.

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant