Implement user authentication

This commit is contained in:
Nat 2021-04-29 17:51:26 -03:00
parent 4bc1c71a7f
commit 71c3afbe36
3 changed files with 309 additions and 63 deletions

187
package-lock.json generated
View File

@ -11,8 +11,9 @@
"@react-navigation/native": "5.1.1", "@react-navigation/native": "5.1.1",
"@react-navigation/stack": "5.2.3", "@react-navigation/stack": "5.2.3",
"expo": "^38.0.9", "expo": "^38.0.9",
"expo-linking": "^1.0.3", "expo-linking": "^1.0.7",
"expo-status-bar": "^1.0.2", "expo-status-bar": "^1.0.2",
"expo-web-browser": "~8.3.1",
"react": "~16.11.0", "react": "~16.11.0",
"react-dom": "~16.11.0", "react-dom": "~16.11.0",
"react-native": "https://github.com/expo/react-native/archive/sdk-38.0.2.tar.gz", "react-native": "https://github.com/expo/react-native/archive/sdk-38.0.2.tar.gz",
@ -2867,6 +2868,17 @@
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
"integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs="
}, },
"node_modules/compare-urls": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/compare-urls/-/compare-urls-2.0.0.tgz",
"integrity": "sha512-eCJcWn2OYFEIqbm70ta7LQowJOOZZqq1a2YbbFCFI1uwSvj+TWMwXVn7vPR1ceFNcAIt5RSTDbwdlX82gYLTkA==",
"dependencies": {
"normalize-url": "^2.0.1"
},
"engines": {
"node": ">=6"
}
},
"node_modules/compare-versions": { "node_modules/compare-versions": {
"version": "3.6.0", "version": "3.6.0",
"resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz",
@ -3610,13 +3622,25 @@
} }
}, },
"node_modules/expo-linking": { "node_modules/expo-linking": {
"version": "1.0.3", "version": "1.0.7",
"resolved": "https://registry.npmjs.org/expo-linking/-/expo-linking-1.0.3.tgz", "resolved": "https://registry.npmjs.org/expo-linking/-/expo-linking-1.0.7.tgz",
"integrity": "sha512-Bzm8qVlSRBmoQcnveBBLO4ea/AEW4t10WFiJ18m/w8OnEXbsP7WT39UyhTuFsrnjYSLMjW4/JXkfmswBOhISuA==", "integrity": "sha512-AhvntaU1PItf73Tm5J7tUVEgCjz/7SeuXg4vLCQgFsEywU0E4Z/jgfQ+30omrrvalBKL3L18cHG9Y4pWmROqgg==",
"dependencies": { "dependencies": {
"expo-constants": "~9.1.1", "expo-constants": "~9.2.0",
"qs": "^6.5.0", "qs": "^6.5.0",
"url-parse": "^1.4.4" "url-parse": "^1.4.4"
},
"peerDependencies": {
"react-native": "*"
}
},
"node_modules/expo-linking/node_modules/expo-constants": {
"version": "9.2.0",
"resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-9.2.0.tgz",
"integrity": "sha512-WKwiEMvBgPrEPEyZKm21UUB2KWQux9OCWf6ZDORLTln7kO3rsbaJEprfWUWTP7AxyaLMYfN+/0WFHjZc25SZWQ==",
"dependencies": {
"fbjs": "1.0.0",
"uuid": "^3.3.2"
} }
}, },
"node_modules/expo-location": { "node_modules/expo-location": {
@ -3654,6 +3678,18 @@
"resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-1.0.2.tgz", "resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-1.0.2.tgz",
"integrity": "sha512-5313u744GcLzCadxIPXyTkYw77++UXv1dXCuhYDxDbtsEf93iMra7WSvzyE8a7mRQLIIPRuGnBOdrL/V1C7EOQ==" "integrity": "sha512-5313u744GcLzCadxIPXyTkYw77++UXv1dXCuhYDxDbtsEf93iMra7WSvzyE8a7mRQLIIPRuGnBOdrL/V1C7EOQ=="
}, },
"node_modules/expo-web-browser": {
"version": "8.3.1",
"resolved": "https://registry.npmjs.org/expo-web-browser/-/expo-web-browser-8.3.1.tgz",
"integrity": "sha512-mDxSNpc/Ww/RX6MhmPRUWo2xNi8HGZ1TDMqIjTvUzrL7pGG9VerX0EDMhfLgo6c7KVOY1ngbTyybApZTXgPCOQ==",
"dependencies": {
"compare-urls": "^2.0.0"
},
"peerDependencies": {
"react": "*",
"react-native": "*"
}
},
"node_modules/expo/node_modules/babel-preset-expo": { "node_modules/expo/node_modules/babel-preset-expo": {
"version": "8.2.3", "version": "8.2.3",
"resolved": "https://registry.npmjs.org/babel-preset-expo/-/babel-preset-expo-8.2.3.tgz", "resolved": "https://registry.npmjs.org/babel-preset-expo/-/babel-preset-expo-8.2.3.tgz",
@ -4658,6 +4694,14 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/is-plain-obj": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
"integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-plain-object": { "node_modules/is-plain-object": {
"version": "2.0.4", "version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
@ -6203,6 +6247,40 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/normalize-url": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz",
"integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==",
"dependencies": {
"prepend-http": "^2.0.0",
"query-string": "^5.0.1",
"sort-keys": "^2.0.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/normalize-url/node_modules/query-string": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz",
"integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==",
"dependencies": {
"decode-uri-component": "^0.2.0",
"object-assign": "^4.1.0",
"strict-uri-encode": "^1.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/normalize-url/node_modules/strict-uri-encode": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
"integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/npm-run-path": { "node_modules/npm-run-path": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
@ -6716,6 +6794,14 @@
"resolved": "https://registry.npmjs.org/pouchdb-collections/-/pouchdb-collections-1.0.1.tgz", "resolved": "https://registry.npmjs.org/pouchdb-collections/-/pouchdb-collections-1.0.1.tgz",
"integrity": "sha1-/mOhfal3YRq+98uAJssalVP9g1k=" "integrity": "sha1-/mOhfal3YRq+98uAJssalVP9g1k="
}, },
"node_modules/prepend-http": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
"integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=",
"engines": {
"node": ">=4"
}
},
"node_modules/pretty-format": { "node_modules/pretty-format": {
"version": "23.6.0", "version": "23.6.0",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-23.6.0.tgz", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-23.6.0.tgz",
@ -7980,6 +8066,17 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
}, },
"node_modules/sort-keys": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz",
"integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=",
"dependencies": {
"is-plain-obj": "^1.0.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/source-map": { "node_modules/source-map": {
"version": "0.5.7", "version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
@ -11522,6 +11619,14 @@
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
"integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs="
}, },
"compare-urls": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/compare-urls/-/compare-urls-2.0.0.tgz",
"integrity": "sha512-eCJcWn2OYFEIqbm70ta7LQowJOOZZqq1a2YbbFCFI1uwSvj+TWMwXVn7vPR1ceFNcAIt5RSTDbwdlX82gYLTkA==",
"requires": {
"normalize-url": "^2.0.1"
}
},
"compare-versions": { "compare-versions": {
"version": "3.6.0", "version": "3.6.0",
"resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz",
@ -12249,13 +12354,24 @@
} }
}, },
"expo-linking": { "expo-linking": {
"version": "1.0.3", "version": "1.0.7",
"resolved": "https://registry.npmjs.org/expo-linking/-/expo-linking-1.0.3.tgz", "resolved": "https://registry.npmjs.org/expo-linking/-/expo-linking-1.0.7.tgz",
"integrity": "sha512-Bzm8qVlSRBmoQcnveBBLO4ea/AEW4t10WFiJ18m/w8OnEXbsP7WT39UyhTuFsrnjYSLMjW4/JXkfmswBOhISuA==", "integrity": "sha512-AhvntaU1PItf73Tm5J7tUVEgCjz/7SeuXg4vLCQgFsEywU0E4Z/jgfQ+30omrrvalBKL3L18cHG9Y4pWmROqgg==",
"requires": { "requires": {
"expo-constants": "~9.1.1", "expo-constants": "~9.2.0",
"qs": "^6.5.0", "qs": "^6.5.0",
"url-parse": "^1.4.4" "url-parse": "^1.4.4"
},
"dependencies": {
"expo-constants": {
"version": "9.2.0",
"resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-9.2.0.tgz",
"integrity": "sha512-WKwiEMvBgPrEPEyZKm21UUB2KWQux9OCWf6ZDORLTln7kO3rsbaJEprfWUWTP7AxyaLMYfN+/0WFHjZc25SZWQ==",
"requires": {
"fbjs": "1.0.0",
"uuid": "^3.3.2"
}
}
} }
}, },
"expo-location": { "expo-location": {
@ -12293,6 +12409,14 @@
"resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-1.0.2.tgz", "resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-1.0.2.tgz",
"integrity": "sha512-5313u744GcLzCadxIPXyTkYw77++UXv1dXCuhYDxDbtsEf93iMra7WSvzyE8a7mRQLIIPRuGnBOdrL/V1C7EOQ==" "integrity": "sha512-5313u744GcLzCadxIPXyTkYw77++UXv1dXCuhYDxDbtsEf93iMra7WSvzyE8a7mRQLIIPRuGnBOdrL/V1C7EOQ=="
}, },
"expo-web-browser": {
"version": "8.3.1",
"resolved": "https://registry.npmjs.org/expo-web-browser/-/expo-web-browser-8.3.1.tgz",
"integrity": "sha512-mDxSNpc/Ww/RX6MhmPRUWo2xNi8HGZ1TDMqIjTvUzrL7pGG9VerX0EDMhfLgo6c7KVOY1ngbTyybApZTXgPCOQ==",
"requires": {
"compare-urls": "^2.0.0"
}
},
"extend-shallow": { "extend-shallow": {
"version": "3.0.2", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
@ -13034,6 +13158,11 @@
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
"integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8="
}, },
"is-plain-obj": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
"integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4="
},
"is-plain-object": { "is-plain-object": {
"version": "2.0.4", "version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
@ -14322,6 +14451,33 @@
"remove-trailing-separator": "^1.0.1" "remove-trailing-separator": "^1.0.1"
} }
}, },
"normalize-url": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz",
"integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==",
"requires": {
"prepend-http": "^2.0.0",
"query-string": "^5.0.1",
"sort-keys": "^2.0.0"
},
"dependencies": {
"query-string": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz",
"integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==",
"requires": {
"decode-uri-component": "^0.2.0",
"object-assign": "^4.1.0",
"strict-uri-encode": "^1.0.0"
}
},
"strict-uri-encode": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
"integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM="
}
}
},
"npm-run-path": { "npm-run-path": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
@ -14708,6 +14864,11 @@
"resolved": "https://registry.npmjs.org/pouchdb-collections/-/pouchdb-collections-1.0.1.tgz", "resolved": "https://registry.npmjs.org/pouchdb-collections/-/pouchdb-collections-1.0.1.tgz",
"integrity": "sha1-/mOhfal3YRq+98uAJssalVP9g1k=" "integrity": "sha1-/mOhfal3YRq+98uAJssalVP9g1k="
}, },
"prepend-http": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
"integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc="
},
"pretty-format": { "pretty-format": {
"version": "23.6.0", "version": "23.6.0",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-23.6.0.tgz", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-23.6.0.tgz",
@ -15789,6 +15950,14 @@
} }
} }
}, },
"sort-keys": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz",
"integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=",
"requires": {
"is-plain-obj": "^1.0.0"
}
},
"source-map": { "source-map": {
"version": "0.5.7", "version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",

View File

@ -14,8 +14,9 @@
"@react-navigation/native": "5.1.1", "@react-navigation/native": "5.1.1",
"@react-navigation/stack": "5.2.3", "@react-navigation/stack": "5.2.3",
"expo": "^38.0.9", "expo": "^38.0.9",
"expo-linking": "^1.0.3", "expo-linking": "^1.0.7",
"expo-status-bar": "^1.0.2", "expo-status-bar": "^1.0.2",
"expo-web-browser": "~8.3.1",
"react": "~16.11.0", "react": "~16.11.0",
"react-dom": "~16.11.0", "react-dom": "~16.11.0",
"react-native": "https://github.com/expo/react-native/archive/sdk-38.0.2.tar.gz", "react-native": "https://github.com/expo/react-native/archive/sdk-38.0.2.tar.gz",

View File

@ -10,41 +10,101 @@ import {
} from "react-native"; } from "react-native";
import AsyncStorage from "@react-native-async-storage/async-storage"; import AsyncStorage from "@react-native-async-storage/async-storage";
import * as Linking from "expo-linking";
import * as WebBrowser from "expo-web-browser";
import Constants from "expo-constants";
const TEST_IMAGE = "https://cache.desktopnexus.com/thumbseg/2255/2255124-bigthumbnail.jpg"; async function postForm(url, data, token = false) {
const TEST_PROFILE = { // Send a POST request with data formatted with FormData returning JSON
username: "njms", let form = new FormData();
acct: "njms", for (let key in data) {
display_name: "Nat🔆", form.append(key, data[key]);
locked: false,
bot: false,
note: "Yeah heart emoji.",
avatar: TEST_IMAGE,
followers_count: "1 jillion",
statuses_count: 334,
fields: [
{
name: "Blog",
value: "<a href=\"https://njms.ca\">https://njms.ca</a>",
verified_at: "some time"
},
{
name: "Github",
value: "<a href=\"https://github.com/natjms\">https://github.com/natjms</a>",
verified_at: null
} }
]
}; const response = await fetch(url, {
method: "POST",
body: form,
headers: token
? { "Authorization": `Bearer ${token}`, }
: {},
});
return response.json();
}
async function get(url, token = false) {
const response = await fetch(url, {
method: "GET",
headers: token
? { "Authorization": `Bearer ${token}`, }
: {},
});
return response.json();
}
const AuthenticateJsx = ({navigation}) => { const AuthenticateJsx = ({navigation}) => {
const REDIRECT_URI = Linking.makeUrl("authenticate");
const [state, setState] = useState({ const [state, setState] = useState({
acct: "", instance: "",
password: "",
authChecked: false, authChecked: false,
}); });
const _handleUrl = async ({ url }) => {
// When the app is foregrounded after authorizing the app from their
// instance's website...
if (Constants.platform.ios) {
WebBrowser.dismissBrowser();
} else {
Linking.removeEventListener("url", _handleUrl)
}
const { path, queryParams } = Linking.parse(url);
const instance = await AsyncStorage.getItem("@user_instance");
const api = `https://${instance}`;
const app = JSON.parse(
await AsyncStorage.getItem("@app_object")
);
// Fetch the access token
const tokenRequestBody = {
client_id: app.client_id,
client_secret: app.client_secret,
redirect_uri: REDIRECT_URI,
grant_type: "authorization_code",
code: queryParams.code,
scope: "read write follow push",
};
const token = await postForm(`${api}/oauth/token`, tokenRequestBody);
// Store the token
AsyncStorage.setItem("@user_token", JSON.stringify(token));
const profile = await get(
`${api}/api/v1/accounts/verify_credentials`,
token.access_token
);
await AsyncStorage.multiSet([
[ "@user_profile", JSON.stringify(profile), ],
[ // TODO: Enable storing notifications
"@user_notifications",
JSON.stringify({
unread: false,
memory: []
}),
],
]);
navigation.navigate("Feed");
};
useEffect(() => { useEffect(() => {
AsyncStorage.getItem("@user_profile").then((profile) => { Linking.addEventListener("url", _handleUrl);
AsyncStorage
.getItem("@user_profile")
.then(profile => {
if (profile) { if (profile) {
navigation.navigate("Feed"); navigation.navigate("Feed");
} else { } else {
@ -53,21 +113,44 @@ const AuthenticateJsx = ({navigation}) => {
}); });
}, []); }, []);
const loginCallback = () => { const _login = async () => {
const initialization = [ const url = `https://${state.instance}`;
[ "@user_profile", JSON.stringify(TEST_PROFILE) ],
[
"@user_notifications",
JSON.stringify({
unread: false,
memory: [{ id: 1 }, { id: 2 }],
})
]
];
AsyncStorage.multiSet(initialization).then(() => { let appJSON = await AsyncStorage.getItem("@app_object");
navigation.navigate("Feed"); let app;
// Ensure the app has been created
if (appJSON == null) {
// Register app: https://docs.joinmastodon.org/methods/apps/#create-an-application
app = await postForm(`${url}/api/v1/apps`, {
client_name: "Resin",
redirect_uris: REDIRECT_URI,
scopes: "read write follow push",
website: "https://github.com/natjms/resin",
}); });
await AsyncStorage
.setItem("@app_object", JSON.stringify(app))
} else {
// The app has already been registered
app = JSON.parse(appJSON);
}
// Store the domain name of the instance for use in
// the _handleUrl callback
// NOTE: state.instance is not accessible from _handleUrl; this
// probably has something to do with the fact that the app loses
// focus when WebBrowser.openAuthSessionAsync gets called.
await AsyncStorage.setItem("@user_instance", state.instance);
// Get the user to authorize the app
await WebBrowser.openAuthSessionAsync(
`${url}/oauth/authorize`
+ `?client_id=${app.client_id}`
+ `&scope=read+write+follow+push`
+ `&redirect_uri=${REDIRECT_URI}`
+ `&response_type=code`
);
}; };
return ( return (
@ -81,25 +164,18 @@ const AuthenticateJsx = ({navigation}) => {
resizeMode = { "contain" } resizeMode = { "contain" }
source = { require("assets/logo/logo-standalone.png") }/> source = { require("assets/logo/logo-standalone.png") }/>
</View> </View>
<Text style = { styles.label }> Account name </Text> <Text style = { styles.label }> Instance domain name </Text>
<TextInput <TextInput
style = { styles.input } style = { styles.input }
placeholder = { "name@domain.tld" } placeholder = { "domain.tld" }
value = { state.instance }
onChangeText = { onChangeText = {
value => setState({ ...state, acct: value }) value => setState({ ...state, instance: value })
}/> }/>
<Text style = { styles.label }> Password </Text>
<TextInput
style = { styles.input }
placeholder = { "************" }
secureTextEntry = { true }
onChangeText = {
value => setState({ ...state, password: value })
}/>
<TouchableOpacity <TouchableOpacity
style = { styles.login.button } style = { styles.login.button }
onPress = { loginCallback }> onPress = { _login }>
<Text style = { styles.login.label }> Login </Text> <Text style = { styles.login.label }> Login </Text>
</TouchableOpacity> </TouchableOpacity>
</View> </View>