aboutsummaryrefslogtreecommitdiff
path: root/src/ejabberd_oauth_rest.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/ejabberd_oauth_rest.erl')
-rw-r--r--src/ejabberd_oauth_rest.erl149
1 files changed, 149 insertions, 0 deletions
diff --git a/src/ejabberd_oauth_rest.erl b/src/ejabberd_oauth_rest.erl
new file mode 100644
index 000000000..6af67996b
--- /dev/null
+++ b/src/ejabberd_oauth_rest.erl
@@ -0,0 +1,149 @@
+%%%-------------------------------------------------------------------
+%%% File : ejabberd_oauth_rest.erl
+%%% Author : Alexey Shchepin <alexey@process-one.net>
+%%% Purpose : OAUTH2 REST backend
+%%% Created : 26 Jul 2016 by Alexey Shchepin <alexey@process-one.net>
+%%%
+%%%
+%%% ejabberd, Copyright (C) 2002-2019 ProcessOne
+%%%
+%%% This program is free software; you can redistribute it and/or
+%%% modify it under the terms of the GNU General Public License as
+%%% published by the Free Software Foundation; either version 2 of the
+%%% License, or (at your option) any later version.
+%%%
+%%% This program is distributed in the hope that it will be useful,
+%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+%%% General Public License for more details.
+%%%
+%%% You should have received a copy of the GNU General Public License
+%%% along with this program; if not, write to the Free Software
+%%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+%%% 02111-1307 USA
+%%%
+%%%-------------------------------------------------------------------
+
+-module(ejabberd_oauth_rest).
+-behaviour(ejabberd_oauth).
+
+-export([init/0,
+ store/1,
+ lookup/1,
+ clean/1,
+ lookup_client/1,
+ store_client/1]).
+
+-include("ejabberd_oauth.hrl").
+-include("logger.hrl").
+-include("jid.hrl").
+
+init() ->
+ rest:start(ejabberd_config:get_myname()),
+ ok.
+
+store(R) ->
+ Path = path(<<"store">>),
+ %% Retry 2 times, with a backoff of 500millisec
+ {User, Server} = R#oauth_token.us,
+ SJID = jid:encode({User, Server, <<"">>}),
+ case rest:with_retry(
+ post,
+ [ejabberd_config:get_myname(), Path, [],
+ {[{<<"token">>, R#oauth_token.token},
+ {<<"user">>, SJID},
+ {<<"scope">>, R#oauth_token.scope},
+ {<<"expire">>, R#oauth_token.expire}
+ ]}], 2, 500) of
+ {ok, Code, _} when Code == 200 orelse Code == 201 ->
+ ok;
+ Err ->
+ ?ERROR_MSG("Failed to store oauth record ~p: ~p", [R, Err]),
+ {error, db_failure}
+ end.
+
+lookup(Token) ->
+ Path = path(<<"lookup">>),
+ case rest:with_retry(post, [ejabberd_config:get_myname(), Path, [],
+ {[{<<"token">>, Token}]}],
+ 2, 500) of
+ {ok, 200, {Data}} ->
+ SJID = proplists:get_value(<<"user">>, Data, <<>>),
+ JID = jid:decode(SJID),
+ US = {JID#jid.luser, JID#jid.lserver},
+ Scope = proplists:get_value(<<"scope">>, Data, []),
+ Expire = proplists:get_value(<<"expire">>, Data, 0),
+ {ok, #oauth_token{token = Token,
+ us = US,
+ scope = Scope,
+ expire = Expire}};
+ {ok, 404, _Resp} ->
+ error;
+ Other ->
+ ?ERROR_MSG("Unexpected response for oauth lookup: ~p", [Other]),
+ error
+ end.
+
+clean(_TS) ->
+ ok.
+
+path(Path) ->
+ Base = ejabberd_option:ext_api_path_oauth(),
+ <<Base/binary, "/", Path/binary>>.
+
+store_client(#oauth_client{client_id = ClientID,
+ client_name = ClientName,
+ grant_type = GrantType,
+ options = Options} = R) ->
+ Path = path(<<"store_client">>),
+ SGrantType =
+ case GrantType of
+ password -> <<"password">>;
+ implicit -> <<"implicit">>
+ end,
+ SOptions = misc:term_to_base64(Options),
+ %% Retry 2 times, with a backoff of 500millisec
+ case rest:with_retry(
+ post,
+ [ejabberd_config:get_myname(), Path, [],
+ {[{<<"client_id">>, ClientID},
+ {<<"client_name">>, ClientName},
+ {<<"grant_type">>, SGrantType},
+ {<<"options">>, SOptions}
+ ]}], 2, 500) of
+ {ok, Code, _} when Code == 200 orelse Code == 201 ->
+ ok;
+ Err ->
+ ?ERROR_MSG("Failed to store oauth record ~p: ~p", [R, Err]),
+ {error, db_failure}
+ end.
+
+lookup_client(ClientID) ->
+ Path = path(<<"lookup_client">>),
+ case rest:with_retry(post, [ejabberd_config:get_myname(), Path, [],
+ {[{<<"client_id">>, ClientID}]}],
+ 2, 500) of
+ {ok, 200, {Data}} ->
+ ClientName = proplists:get_value(<<"client_name">>, Data, <<>>),
+ SGrantType = proplists:get_value(<<"grant_type">>, Data, <<>>),
+ GrantType =
+ case SGrantType of
+ <<"password">> -> password;
+ <<"implicit">> -> implicit
+ end,
+ SOptions = proplists:get_value(<<"options">>, Data, <<>>),
+ case misc:base64_to_term(SOptions) of
+ {term, Options} ->
+ {ok, #oauth_client{client_id = ClientID,
+ client_name = ClientName,
+ grant_type = GrantType,
+ options = Options}};
+ _ ->
+ error
+ end;
+ {ok, 404, _Resp} ->
+ error;
+ Other ->
+ ?ERROR_MSG("Unexpected response for oauth lookup: ~p", [Other]),
+ error
+ end.