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
5 changes: 1 addition & 4 deletions .lycheeignore
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,8 @@ https://github.com/gjwgit/myapp/blob/main/README.md
https://server/POD_NAME/APP_NAME/data/FILE_PATH
https://host/
https://pods.au/me/app/data
https://github.com/anusii/mypod/blob/dev/CHANGELOG.md
https://anusii.github.io/mypod/
https://anusii.github.io/mypod/client-profile.jsonld
https://anusii.github.io/mypod/redirect.html
https://your-solid-server/
https://gjwgit.github.io/rolopod/client-profile.jsonld

# 20260605 gjw Failing solid servers

Expand Down
25 changes: 25 additions & 0 deletions client-profile.jsonld
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"@context": "https://www.w3.org/ns/solid/oidc-context.jsonld",
"client_id": "https://gjwgit.github.io/rolopod/client-profile.jsonld",
"client_name": "RoloPod",
"application_type": "native",
"redirect_uris": [
"https://rolopod.solidcommunity.au/redirect.html",
"com.togaware.rolopod://redirect",
"http://localhost:4400/redirect.html"
],
"post_logout_redirect_uris": [
"https://rolopod.solidcommunity.au/redirect.html",
"com.togaware.rolopod://redirect",
"http://localhost:4400/redirect.html"
],
"scope": "openid profile offline_access webid",
"grant_types": [
"authorization_code",
"refresh_token"
],
"response_types": [
"code"
],
"token_endpoint_auth_method": "none"
}
15 changes: 8 additions & 7 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

library;

import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:flutter/material.dart';

import 'package:provider/provider.dart';
Expand Down Expand Up @@ -103,13 +104,13 @@ class _RoloPodAppState extends State<RoloPodApp> {
image: const AssetImage('assets/images/app_image.jpg'),
logo: const AssetImage('assets/images/app_icon.png'),
link: 'https://github.com/gjwgit/rolopod',
clientId:
'https://solidcommunity.au/apps/rolopod/client-profile.jsonld',
redirectUris: [
'http://localhost:4400/redirect',
'com.togaware.rolopod://redirect',
'https://solidcommunity.au/apps/rolopod/redirect.html',
],
clientId: 'https://gjwgit.github.io/rolopod/client-profile.jsonld',
redirectUris: kIsWeb
? ['${Uri.base.origin}/redirect.html']
: const [
'com.togaware.rolopod://redirect',
'http://localhost:4400/redirect.html',
],
child: const AppScaffold(),
),
);
Expand Down
8 changes: 8 additions & 0 deletions macos/Runner/DebugProfile.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,13 @@
<true/>
<key>com.apple.security.network.server</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>keychain-access-groups</key>
<array/>
<key>com.apple.security.keychain</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
</dict>
</plist>
12 changes: 12 additions & 0 deletions macos/Runner/Release.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,17 @@
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>keychain-access-groups</key>
<array/>
<key>com.apple.security.keychain</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
</dict>
</plist>
2 changes: 1 addition & 1 deletion support/flutter.mk
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ LOC := $(shell if [ -f support/loc.sh ]; then echo support/loc.sh; \

.PHONY: chrome
chrome:
flutter run -d chrome --release
flutter run -d chrome --release --web-port=4400

# 20220503 gjw The following fails if the target files already exist -
# just needs to be run once.
Expand Down
30 changes: 0 additions & 30 deletions web/callback.html

This file was deleted.

122 changes: 122 additions & 0 deletions web/redirect.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
<!--
This HTML page works as a redirect_uri, post_logout_redirect_uri, frontchannel_logout_uri
but for frontchannel_logout_uri to work, it must be called like this:

/redirect.html?requestType=front-channel-logout
-->
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8">
<title>Flutter Oidc Redirect</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript">
const stateNamespace = 'state';
const stateResponseNamespace = 'response.state';
const requestNamespace = 'request';

const requestBroadcastChannel = 'oidc_flutter_web/request';
const redirectBroadcastChannel = 'oidc_flutter_web/redirect';


//if the OP isn't requesting logout, handle redirect.
if (!handleFrontChannelLogout()) {
handleRedirect();
}

function handleRedirect() {
// For supported browsers: https://caniuse.com/broadcastchannel
var bc = new BroadcastChannel(redirectBroadcastChannel);
bc.postMessage(window.location.toString());
bc.close();
//The rest of this function handles same page redirects
let dataSrc;
dataSrc = new URLSearchParams(window.location.search);
var state = dataSrc.get('state');
if (!state) {
if (window.location.hash) {
dataSrc = new URLSearchParams(
window.location.hash.substring(1)
);
state = dataSrc.get('state');
}
}
if (!state) {
return;
}
const stateDataRaw = getLocalStorage(stateNamespace, state);
if (!stateDataRaw) {
console.error('state not found, key: ' + state);
return;
}
setLocalStorage(stateResponseNamespace, state, window.location.toString());
//we call JSON.parse twice, since shared_preferences double encodes json strings for some reason.
const parsedStateString = JSON.parse(stateDataRaw);
if (!parsedStateString) {
console.error('parsed state is null');
return;
}
// Read the mode from the state.
const webLaunchMode = parsedStateString.options?.webLaunchMode;
if (!webLaunchMode) {
console.error('webLaunchMode not found in parsed state.');
return;
}
if (webLaunchMode != 'samePage') {
return;
}
const original_uri = parsedStateString.original_uri;
if (!original_uri) {
console.warn("it's preferred that original_uri is used when webLaunchMode is samePage.");
return;
}
window.location.assign(original_uri);
}

function handleFrontChannelLogout() {
const queryParams = new URLSearchParams(window.location.search);
if (queryParams.get('requestType') == 'front-channel-logout') {
// For supported browsers: https://caniuse.com/broadcastchannel
var bc = new BroadcastChannel(requestBroadcastChannel);
bc.postMessage(window.location.toString());
bc.close();
// this puts a marker for the flutter app that the user wants to logout.
//
// in the flutter app, if this marker exists,
// we don't auth the cached user in `UserManager.init()`, and we clear the cached data.
setLocalStorage(requestNamespace, 'front-channel-logout', window.location.toString());
return true;
}
return false;
}

function getLocalStorage(namespace, key) {
const rawRes = localStorage.getItem('oidc.' + namespace + '.' + key);
if (!rawRes) {
return null;
}
return rawRes;
}
function setLocalStorage(namespace, key, value) {
const keysEntryKey = 'oidc.keys.' + namespace;
var keys = localStorage.getItem(keysEntryKey);
if (!keys) {
keys = "[]";
}
const parsedKeys = JSON.parse(keys);
if (!(parsedKeys instanceof Array)) {
console.error('parsedKeys is not an array.', parsedKeys);
}
parsedKeys.push(key);
localStorage.setItem(keysEntryKey, JSON.stringify(parsedKeys));
localStorage.setItem('oidc.' + namespace + '.' + key, value);
}
</script>
</head>

<body>
<h3>Authentication completed! Please close this page.</h3>
</body>

</html>
Loading