authentication works
[anoweco.git] / www / auth.php
1 <?php
2 namespace anoweco;
3 /**
4  * IndieAuth endpoint
5  *
6  * @author Christian Weiske <cweiske@cweiske.de>
7  */
8 header('HTTP/1.0 500 Internal Server Error');
9 require 'www-header.php';
10
11 function getOrCreateUser($mode, $name, $email)
12 {
13     if ($mode == 'anonymous') {
14         $name  = 'Anonymous';
15         $email = '';
16     } else {
17         if ($name == '') {
18             $name = 'Anonymous';
19         }
20     }
21     $imageurl = getImageUrl($email);
22
23     $storage = new Storage();
24     $id = $storage->findUser($name, $imageurl);
25     if ($id !== null) {
26         return $id;
27     }
28     $id = $storage->createUser($name, $imageurl);
29     return $id;
30 }
31
32 function getImageUrl($email)
33 {
34     //FIXME: libravatar
35     return Urls::userImg((object)['user_imageurl' => '']);
36 }
37
38 header('IndieAuth: authorization_endpoint');
39 if ($_SERVER['REQUEST_METHOD'] == 'GET') {
40     if (count($_GET) == 0) {
41         //no parameters - show the index page
42         header('HTTP/1.0 200 OK');
43         header('Content-Type: text/html');
44         render('auth-index', ['baseurl' => Urls::full('/')]);
45         exit();
46     }
47
48     $me            = verifyUrlParameter($_GET, 'me');
49     $redirect_uri  = verifyUrlParameter($_GET, 'redirect_uri');
50     $client_id     = verifyUrlParameter($_GET, 'client_id');
51     $state         = getOptionalParameter($_GET, 'state', null);
52     $response_type = getOptionalParameter($_GET, 'response_type', 'id');
53     $scope         = getOptionalParameter($_GET, 'scope', null);
54
55     //FIXME: if $me is an actual user, load his data
56
57     //let the user choose his identity
58     header('HTTP/1.0 200 OK');
59     render(
60         'auth-choose',
61         array(
62             'auth' => array(
63                 'redirect_uri'  => $redirect_uri,
64                 'client_id'     => $client_id,
65                 'state'         => $state,
66                 'response_type' => $response_type,
67                 'scope'         => $scope,
68             ),
69             'formaction' => '/auth.php?action=login',
70         )
71     );
72     exit();
73 } else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
74     if (isset($_GET['action']) && $_GET['action'] == 'login') {
75         //log the user in
76         $auth = $_POST['auth'];
77         $redirect_uri  = verifyUrlParameter($auth, 'redirect_uri');
78         $client_id     = verifyUrlParameter($auth, 'client_id');
79         $state         = getOptionalParameter($auth, 'state', null);
80         $response_type = getOptionalParameter($auth, 'response_type', 'id');
81         $scope         = getOptionalParameter($auth, 'scope', null);
82
83         $id = $_POST['id'];
84         verifyParameter($id, 'mode');
85
86         $userId = getOrCreateUser(
87             $id['mode'], trim($id['name']), trim($id['email'])
88         );
89         $me = Urls::full(Urls::user($userId));
90
91         $code = base64_encode(
92             http_build_query(
93                 [
94                     'emoji'     => '\360\237\222\251',
95                     'me'        => $me,
96                     'scope'     => $scope,
97                     'signature' => 'FIXME',
98                 ]
99             )
100         );
101
102         //redirect back to client
103         $url = new \Net_URL2($redirect_uri);
104         if ($response_type == 'code') {
105             $url->setQueryVariable('code', $code);
106         }
107         $url->setQueryVariable('me', $me);
108         $url->setQueryVariable('state', $state);
109         header('Location: ' . $url->getURL());
110         exit();
111     } else {
112         //auth code verification
113         $code         = base64_decode(verifyParameter($_POST, 'code'));
114         $redirect_uri = verifyUrlParameter($_POST, 'redirect_uri');
115         $client_id    = verifyUrlParameter($_POST, 'client_id');
116         $state        = getOptionalParameter($_POST, 'state', null);
117
118         parse_str($code, $codeParts);
119         $emoji     = verifyParameter($codeParts, 'emoji');
120         $signature = verifyParameter($codeParts, 'signature');
121         $me        = verifyUrlParameter($codeParts, 'me');
122         if ($emoji != '\360\237\222\251') {
123             error('Dog poo missing');
124         }
125         if ($signature != 'FIXME') {
126             error('Invalid signature');
127         }
128         header('HTTP/1.0 200 OK');
129         header('Content-type: application/x-www-form-urlencoded');
130         echo http_build_query(['me' => $me]);
131         exit();
132     }
133 }
134 ?>