grim/prosody_mod_auth_jetbrains_hub
Clone
Summary
Browse
Changes
Graph
Initial revision
2019-10-19, Gary Kramlich
18e22b4ce5f4
Initial revision
-- Prosody IM
-- Copyright (C) 2008-2013 Matthew Wild
-- Copyright (C) 2008-2013 Waqas Hussain
-- Copyright (C) 2014 Kim Alvefur
-- Copyright (C) 2019 Gary Kramlich
--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--
local
new_sasl
=
require
"util.sasl"
.
new
;
local
base64
=
require
"util.encodings"
.
base64
.
encode
;
local
have_async
,
async
=
pcall
(
require
,
"util.async"
);
local
log
=
module
.
_log
;
local
host
=
module
.
host
;
local
hub_url
=
module
:
get_option_string
(
"jetbrains_hub_url"
,
""
):
gsub
(
"$host"
,
host
);
if
hub_url
==
""
then
error
(
"jetbrains_hub_url required"
)
end
local
hub_scopes
=
module
:
get_option_string
(
"jetbrains_hub_scopes"
,
""
);
if
hub_scopes
==
""
then
error
(
"jetbrains_hub_scopes required"
)
end
local
hub_client_id
=
module
:
get_option_string
(
"jetbrains_hub_client_id"
,
""
);
if
hub_client_id
==
""
then
error
(
"jetbrains_hub_client_id required"
)
end
local
hub_client_secret
=
module
:
get_option_string
(
"jetbrains_hub_client_secret"
,
""
);
if
hub_client_secret
==
""
then
error
(
"jetbrains_hub_client_secret required"
)
end
local
provider
=
{};
-- globals required by socket.http
if
rawget
(
_G
,
"PROXY"
)
==
nil
then
rawset
(
_G
,
"PROXY"
,
false
)
end
if
rawget
(
_G
,
"base_parsed"
)
==
nil
then
rawset
(
_G
,
"base_parsed"
,
false
)
end
if
not
have_async
then
-- FINE! Set your globals then
prosody
.
unlock_globals
()
require
"ltn12"
require
"socket"
require
"socket.http"
require
"ssl.https"
prosody
.
lock_globals
()
end
local
function
async_http_auth
(
url
,
username
,
password
)
module
:
log
(
"debug"
,
"async_http_auth()"
);
local
http
=
require
"net.http"
;
local
wait
,
done
=
async
.
waiter
();
local
content
,
code
,
request
,
response
;
local
body
=
{
{
name
=
"grant_type"
,
value
=
"password"
};
{
name
=
"username"
,
value
=
username
};
{
name
=
"password"
,
value
=
password
};
{
name
=
"scope"
,
value
=
hub_scopes
};
}
local
ex
=
{
headers
=
{
Authorization
=
"Basic "
..
base64
(
hub_client_id
..
":"
..
hub_client_secret
);
};
body
=
http
.
formencode
(
body
);
}
local
function
cb
(
content_
,
code_
,
request_
,
response_
)
content
,
code
,
request
,
response
=
content_
,
code_
,
request_
,
response_
;
done
();
end
http
.
request
(
url
,
ex
,
cb
);
wait
();
if
code
>=
200
and
code
<=
299
then
module
:
log
(
"debug"
,
"HTTP auth provider confirmed valid password"
);
return
true
;
else
module
:
log
(
"debug"
,
"HTTP auth provider returned status code %d"
,
code
);
end
return
nil
,
"Auth failed. Invalid username or password."
;
end
local
function
sync_http_auth
(
url
,
username
,
password
)
module
:
log
(
"debug"
,
"sync_http_auth()"
);
require
"ltn12"
;
local
http
=
require
"socket.http"
;
local
https
=
require
"ssl.https"
;
local
request
;
if
string.sub
(
url
,
1
,
string.len
(
'https'
))
==
'https'
then
request
=
https
.
request
;
else
request
=
http
.
request
;
end
local
body
=
{
{
name
=
"grant_type"
,
value
=
"password"
};
{
name
=
"username"
,
value
=
username
};
{
name
=
"password"
,
value
=
password
};
{
name
=
"scope"
,
value
=
hub_scopes
};
}
local
_
,
code
,
headers
,
status
=
request
{
url
=
url
,
headers
=
{
Authorization
=
"Basic "
..
base64
(
hub_client_id
..
":"
..
hub_client_secret
);
},
body
=
http
.
formencode
(
body
)
};
if
type
(
code
)
==
"number"
and
code
>=
200
and
code
<=
299
then
module
:
log
(
"debug"
,
"HTTP auth provider confirmed valid password"
);
return
true
;
else
module
:
log
(
"debug"
,
"HTTP auth provider returned status code: "
..
code
);
end
return
nil
,
"Auth failed. Invalid username or password."
;
end
function
provider
.
test_password
(
username
,
password
)
local
url
=
hub_url
..
"/api/rest/oauth2/token"
log
(
"debug"
,
"Testing password for user %s at host %s with URL %s"
,
username
,
host
,
url
);
if
(
have_async
)
then
return
async_http_auth
(
url
,
username
,
password
);
else
return
sync_http_auth
(
url
,
username
,
password
);
end
end
function
provider
.
users
()
return
function
()
return
nil
;
end
end
function
provider
.
set_password
(
username
,
password
)
return
nil
,
"Changing passwords not supported"
;
end
function
provider
.
user_exists
(
username
)
return
true
;
end
function
provider
.
create_user
(
username
,
password
)
return
nil
,
"User creation not supported"
;
end
function
provider
.
delete_user
(
username
)
return
nil
,
"User deletion not supported"
;
end
function
provider
.
get_sasl_handler
()
return
new_sasl
(
host
,
{
plain_test
=
function
(
sasl
,
username
,
password
,
realm
)
return
provider
.
test_password
(
username
,
password
),
true
;
end
});
end
module
:
provides
(
"auth"
,
provider
);