~cytrogen/masto-fe

ref: 0f77cb593c2cfd851f1ca73bd1cfb5e36d2d0bd1 masto-fe/public/auth.js -rw-r--r-- 3.7 KiB
0f77cb59 — Thiago 'Jedi' Cerqueira [chore] Add dev script for easier development loop (#16) 1 year, 1 month ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
document.addEventListener("DOMContentLoaded", async function() {
  await ready();
});

async function ready() {
  const domain = localStorage.getItem('domain');
  let accessToken = localStorage.getItem(`access_token`);

  if (domain) document.getElementById('instance').value = domain;

  const urlParams = new URLSearchParams(window.location.search);
  const code = urlParams.get('code');

  if (domain && code && !accessToken) await getToken(code, domain).then(res => accessToken = res);
  if (accessToken) {
    window.location.href = '/prepare.html';
  }
}

async function auth() {
  setMessage('Please wait');

  const instance = document.getElementById('instance').value;
  const matches = instance.match(/((?:http|https):\/\/)?(.*)/);

  const protocol = matches[1];
  if (protocol) {
    localStorage.setItem('protocol', protocol);
  }
  
  const domain = matches[2];
  if (!domain) {
    setMessage('Invalid instance', false);
    return;
  }
  localStorage.setItem('domain', domain);

  // We need to run this every time in cases like Iceshrimp,
  // where the client id/secret aren't reusable (yet) because
  // they contain use-once session information.
  await registerApp(domain);

  authorize(domain);
}

async function registerApp(domain) {
  setMessage('Registering app');

  const protocol = localStorage.getItem(`protocol`) ?? `https://`;
  const appsUrl = `${protocol}${domain}/api/v1/apps`;
  const formData = new FormData();
  formData.append('client_name', 'Masto-FE (🦥 flavour)');
  formData.append('website', 'https://codeberg.org/superseriousbusiness/masto-fe-standalone');
  formData.append('redirect_uris', document.location.origin + document.location.pathname);
  formData.append('scopes', 'read write follow push');

  // eslint-disable-next-line promise/catch-or-return
  await fetch(appsUrl, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
    },
    body: new URLSearchParams(formData),
  })
    .then(async res => {
      const app = await res.json();
      localStorage.setItem(`client_id`, app.client_id);
      localStorage.setItem(`client_secret`, app.client_secret);
    });
}

function authorize(domain) {
  setMessage('Authorizing');
  const clientId = localStorage.getItem(`client_id`);
  const protocol = localStorage.getItem(`protocol`) ?? `https://`;
  document.location.href = `${protocol}${domain}/oauth/authorize?response_type=code&client_id=${clientId}&redirect_uri=${document.location.origin + document.location.pathname}&scope=read+write+follow+push`;
}

async function getToken(code, domain) {
  setMessage('Getting token');

  const protocol = localStorage.getItem(`protocol`) ?? `https://`;
  const tokenUrl = `${protocol}${domain}/oauth/token`;
  const clientId = localStorage.getItem(`client_id`);
  const clientSecret = localStorage.getItem(`client_secret`);

  const formData = new FormData();
  formData.append('grant_type', 'authorization_code');
  formData.append('code', code);
  formData.append('client_id', clientId);
  formData.append('client_secret', clientSecret);
  formData.append('scope', 'read write follow push');
  formData.append('redirect_uri', document.location.origin + document.location.pathname);


  // eslint-disable-next-line promise/catch-or-return
  return fetch(tokenUrl, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
    },
    body: new URLSearchParams(formData),
  })
    .then(async res => {
      const app = await res.json();
      if (app.access_token) localStorage.setItem(`access_token`, app.access_token);
      return app.access_token;
    });
}

function setMessage(message, disabled = true) {
  document.getElementById('message').textContent = message;
  document.getElementById('btn').disabled = disabled;
}