Skip to content

Commit

Permalink
[4.3] HELP-15032: OAuth fixes for FusionAuth (#6576)
Browse files Browse the repository at this point in the history
Only the path of the provider's profile_url should be searched for
dynamic URL updates. Also provide a convenience function to generate
an auth token for API usage.
  • Loading branch information
jamesaimonetti authored Jun 9, 2020
1 parent 9c136d5 commit 258facd
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 37 deletions.
19 changes: 19 additions & 0 deletions applications/crossbar/src/crossbar_maintenance.erl
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@

-export([db_init/0]).

-export([auth_token/0, auth_token/1]).

-include("crossbar.hrl").
-include_lib("kazoo/include/kz_system_config.hrl").

Expand Down Expand Up @@ -1336,3 +1338,20 @@ db_init() ->
-spec register_views() -> 'ok'.
register_views() ->
kz_datamgr:register_views_from_folder('crossbar').

-spec auth_token() -> kz_term:ne_binary().
auth_token() ->
{'ok', AccountId} = kapps_util:get_master_account_id(),
auth_token(AccountId).

-spec auth_token(kz_term:ne_binary()) -> kz_term:ne_binary().
auth_token(<<AccountId/binary>>) ->
{'ok', _Account} = kzd_accounts:fetch(AccountId),
Context = cb_context:setters(cb_context:new()
,[{fun cb_context:set_resp_status/2, 'success'}
,{fun cb_context:set_doc/2, kz_json:from_list([{<<"account_id">>, AccountId}])}
,{fun cb_context:store/3, 'auth_type', <<"account_api_token">>}
]
),
Context1 = crossbar_auth:create_auth_token(Context, 'cb_api_auth'),
cb_context:auth_token(Context1).
2 changes: 1 addition & 1 deletion applications/crossbar/src/modules/cb_auth.erl
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ delete(Context, ?PROVIDERS_PATH, _Id) ->
maybe_authenticate(Context) ->
case kz_auth:authenticate(cb_context:doc(Context)) of
{'ok', Claims} ->
lager:debug("verified auth: ~p",[Claims]),
lager:debug("verified auth claims: ~p", [Claims]),
Doc = kz_json:set_value(<<"Claims">>, kz_json:from_list(Claims), kz_json:new()),
Setters = [{fun cb_context:set_resp_status/2, 'success'}
,{fun cb_context:set_doc/2, Doc}
Expand Down
60 changes: 29 additions & 31 deletions core/kazoo_auth/doc/example/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,38 +15,36 @@
<script src="//code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="popup.js"></script>
<script>
function test() {
var params = {
client_id :"YOUR_CLIENT_ID",
response_type : "code",
redirect_uri : "WEB_URL",
scope: ["openid", "profile", "email", "https://www.googleapis.com/auth/drive.file"].join(" "),
include_granted_scopes : true,
access_type : "offline",
authuser : 0
};
var url = "https://accounts.google.com/o/oauth2/auth?" + jQuery.param( params );
popup(url, params.redirect_uri, function(data) {
console.log(data);
$("#response")[0].innerText = JSON.stringify(data, null, 2);
});
}
function popup(url, redirect_url, callback) {
var pop = new Popup();
pop.open(url, "oauth", {}, redirect_url).then(function(oauth) {
callback(oauth)
}, function(error) {
console.log(error);
});
}
function test() {
// Adjust params according to your OAuth provider's requirements
var params = {
client_id :"084b9807-c15e-414c-ac49-774a9b156388",
redirect_uri : "http://localhost:8888",
response_type: "code"
};
var url = "http://oauth.provider/oauth2/authorize?" + jQuery.param( params );

function decode() {
var Token = $('#token')[0].value;
var base64Url = Token.split('.')[1];
var base64 = base64Url.replace('-', '+').replace('_', '/');
var decoded = JSON.parse(window.atob(base64));
$('#decoded')[0].innerText = JSON.stringify(decoded, null, 2);
}
popup(url, params.redirect_uri, function(data) {
console.log(data);
$("#response")[0].innerText = JSON.stringify(data, null, 2);
});
}
function popup(url, redirect_url, callback) {
var pop = new Popup();
pop.open(url, "oauth", {}, redirect_url).then(function(oauth) {
callback(oauth)
}, function(error) {
console.log(error);
});
}

function decode() {
var Token = $('#token')[0].value;
var base64Url = Token.split('.')[1];
var base64 = base64Url.replace('-', '+').replace('_', '/');
var decoded = JSON.parse(window.atob(base64));
$('#decoded')[0].innerText = JSON.stringify(decoded, null, 2);
}
</script>
<div style="margin-top:50px;margin-left:100px">
<button onclick="test();">AUTHORIZE</button>
Expand Down
47 changes: 47 additions & 0 deletions core/kazoo_auth/priv/couchdb/providers/generic.oauth.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"_id": "your_provider",
"access_code_url": "https://oauth.server/oauth2/token",
"auth_module": "oauth",
"auth_url": "https://oauth.server/oauth2/token",
"authorization_endpoint": "https://oauth.server/oauth2/auth",
"discovery": "https://oauth.server/.well-known/openid-configuration",
"enabled": true,
"grant_types_supported": [
"authorization_code",
"password",
"urn:ietf:params:oauth:grant-type:jwt-bearer",
"refresh_token"
],
"id_token_alg_values_supported": "RS256",
"issuer_domains": [
"oauth.server"
],
"name": "Your OAuth Provider",
"oauth_url": "https://oauth.server/oauth2/token",
"profile_displayName_field": "name",
"profile_identity_field": "sub",
"profile_url": "https://oauth.server/oauth2/userinfo",
"public_key_discovery_field": "jwks_uri",
"public_key_jwt_field": "kid",
"public_key_jwt_location": "header",
"public_key_lookup_field": "kid",
"public_key_method": "lookup",
"pvt_provider_type": "oauth",
"pvt_type": "provider",
"response_types_supported": [
"code",
"token",
"id_token"
],
"revocation_endpoint": "https://oauth.server/oauth2/revoke",
"scopes": [
"openid",
"email",
"profile"
],
"subject_types_supported": [
"public"
],
"token_endpoint": "https://oauth.server/oauth2/token",
"userinfo_endpoint": "https://oauth.server/oauth2/userinfo"
}
14 changes: 10 additions & 4 deletions core/kazoo_auth/src/kz_auth_profile.erl
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ maybe_load_profile(#{auth_provider := #{profile_url := _ProfileURL} = Provider
Headers = [{<<"host">>, Host}
| profile_authorization_headers(Token, AccessToken)
],
lager:debug("getting profile (~s) from ~s", [Verb, URL]),
lager:debug("fetch profile: ~s ~s", [Verb, URL]),
case kz_http:req(Verb, URL, Headers, <<>>, Options) of
{'ok', 200, _RespHeaders, RespXML} ->
Token#{profile => kz_json:decode(RespXML)};
Expand Down Expand Up @@ -170,9 +170,15 @@ profile_url(#{auth_provider := #{profile_url := ProfileURL} = Provider

-spec maybe_compose_profile_url(kz_term:ne_binary(), map()) -> binary().
maybe_compose_profile_url(Url, Token) ->
case re:run(Url, ?PROFILE_URL_REGEX, ?PROFILE_URL_REGEX_OPTIONS) of
{'match', [_ | _] = Fields} -> compose_profile_url(Url, lists:flatten(Fields), Token);
_ -> Url
{Scheme, Location, Path, Query, Frag} = kz_http_util:urlsplit(Url),

lager:debug("testing URL path ~s against ~s", [Path, ?PROFILE_URL_REGEX]),
case re:run(Path, ?PROFILE_URL_REGEX, ?PROFILE_URL_REGEX_OPTIONS) of
{'match', [_ | _] = Fields} ->
ReplacedPath = compose_profile_url(Path, lists:flatten(Fields), Token),
kz_http_util:urlunsplit({Scheme, Location, ReplacedPath, Query, Frag});
_ ->
Url
end.

-spec compose_profile_url(kz_term:ne_binary(), kz_term:ne_binaries(), map()) -> binary().
Expand Down
4 changes: 3 additions & 1 deletion core/kazoo_auth/src/kz_auth_util.erl
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,10 @@ fetch_access_code(#{auth_app := #{name := ClientId
,{"code", AuthorizationCode}
],
Body = string:join(lists:append(lists:map(fun({K,V}) -> [string:join([K, kz_term:to_list(V)], "=") ] end, Fields)),"&"),
lager:debug("POST ~s: ~s", [URL, Body]),
case kz_http:post(kz_term:to_list(URL), Headers, Body, [{'ssl', [{'versions', ['tlsv1.2']}]}]) of
{'ok', 200, _RespHeaders, RespXML} -> {'ok', kz_json:decode(RespXML)};
{'ok', 200, _RespHeaders, RespJSON} ->
{'ok', kz_json:decode(RespJSON)};
Else ->
lager:error("~p", [Else]),
{'error', Else}
Expand Down

0 comments on commit 258facd

Please sign in to comment.