Skip to content

Commit

Permalink
Merge pull request #448 from ONLYOFFICE/feature/desktop-login
Browse files Browse the repository at this point in the history
Feature/desktop login
  • Loading branch information
AlexeySafronov authored Nov 3, 2021
2 parents 5eaaa6c + baccb13 commit 47d8fbc
Show file tree
Hide file tree
Showing 17 changed files with 135 additions and 106 deletions.
17 changes: 15 additions & 2 deletions common/ASC.FederatedLogin/Helpers/OAuth20TokenHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public OAuth20TokenHelper(IHttpContextAccessor httpContextAccessor, ConsumerFact
ConsumerFactory = consumerFactory;
}

public string RequestCode<T>(string scope = null, Dictionary<string, string> additionalArgs = null) where T : Consumer, IOAuthProvider, new()
public string RequestCode<T>(string scope = null, IDictionary<string, string> additionalArgs = null, IDictionary<string, string> additionalStateArgs = null) where T : Consumer, IOAuthProvider, new()
{
var loginProvider = ConsumerFactory.Get<T>();
var requestUrl = loginProvider.CodeUrl;
Expand All @@ -67,7 +67,20 @@ public OAuth20TokenHelper(IHttpContextAccessor httpContextAccessor, ConsumerFact
if (!string.IsNullOrEmpty(scope)) query += $"&scope={HttpUtility.UrlEncode(scope)}";

var u = HttpContextAccessor.HttpContext.Request.GetUrlRewriter();
var state = HttpUtility.UrlEncode(new UriBuilder(u.Scheme, u.Host, u.Port, $"thirdparty/{loginProvider.Name.ToLower()}/code").Uri.AbsoluteUri);

var stateUriBuilder = new UriBuilder(u.Scheme, u.Host, u.Port, $"thirdparty/{loginProvider.Name.ToLower()}/code");

if (additionalStateArgs != null && additionalStateArgs.Any())
{
var stateQuery = "";
stateQuery = additionalStateArgs.Keys
.Where(a => a != null)
.Aggregate(stateQuery, (current, a) => a != null ? $"{current}&{a.Trim()}={additionalStateArgs[a] ?? "".Trim()}" : null);

stateUriBuilder.Query = stateQuery.Substring(1);
}

var state = HttpUtility.UrlEncode(stateUriBuilder.Uri.AbsoluteUri);
query += $"&state={state}";

if (additionalArgs != null)
Expand Down
63 changes: 22 additions & 41 deletions common/ASC.FederatedLogin/Login.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading;
Expand Down Expand Up @@ -104,10 +105,22 @@ public async Task Invoke(HttpContext context)
{
try
{
var profile = ProviderManager.Process(Auth, context, _params);
var desktop = _params.ContainsKey("desktop") && _params["desktop"] == "true";
IDictionary<string, string> additionalStateArgs = null;

if (desktop)
{
additionalStateArgs = context.Request.Query.ToDictionary(r => r.Key, r => r.Value.FirstOrDefault());
if (!additionalStateArgs.ContainsKey("desktop"))
{
additionalStateArgs.Add("desktop", "true");
}
}

var profile = ProviderManager.Process(Auth, context, null, additionalStateArgs);
if (profile != null)
{
await SendClientData(context, profile);
await SendJsCallback(context, profile);
}
}
catch (ThreadAbortException)
Expand All @@ -116,7 +129,7 @@ public async Task Invoke(HttpContext context)
}
catch (Exception ex)
{
await SendClientData(context, LoginProfile.FromError(Signature, InstanceCrypto, ex));
await SendJsCallback(context, LoginProfile.FromError(Signature, InstanceCrypto, ex));
}
}
else
Expand Down Expand Up @@ -179,48 +192,16 @@ public bool IsReusable
get { return false; }
}

private async Task SendClientData(HttpContext context, LoginProfile profile)
{
switch (Mode)
{
case LoginMode.Redirect:
await RedirectToReturnUrl(context, profile);
break;
case LoginMode.Popup:
await SendJsCallback(context, profile);
break;
}
}

private async Task SendJsCallback(HttpContext context, LoginProfile profile)
{
//Render a page
context.Response.ContentType = "text/html";
await context.Response.WriteAsync(JsCallbackHelper.GetCallbackPage().Replace("%PROFILE%", profile.ToJson()).Replace("%CALLBACK%", Callback));
}

private async Task RedirectToReturnUrl(HttpContext context, LoginProfile profile)
{
var useMinimalProfile = Minimal;
if (useMinimalProfile)
profile = profile.GetMinimalProfile(); //Only id and provider

if (context.Session != null && !useMinimalProfile)
{
//Store in session
context.Response.Redirect(new Uri(ReturnUrl, UriKind.Absolute).AddProfileSession(profile, context).ToString(), true);
}
else if (MemoryCache != null && !useMinimalProfile)
{
context.Response.Redirect(new Uri(ReturnUrl, UriKind.Absolute).AddProfileCache(profile, MemoryCache).ToString(), true);
}
else
{
context.Response.Redirect(new Uri(ReturnUrl, UriKind.Absolute).AddProfile(profile).ToString(), true);
}

await context.Response.CompleteAsync();
return;
await context.Response.WriteAsync(
JsCallbackHelper.GetCallbackPage()
.Replace("%PROFILE%", $"\"{profile.Serialized}\"")
.Replace("%CALLBACK%", Callback)
.Replace("%DESKTOP%", (Mode == LoginMode.Redirect).ToString().ToLowerInvariant())
);
}
}

Expand Down
8 changes: 4 additions & 4 deletions common/ASC.FederatedLogin/LoginProviders/BaseLoginProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,11 @@ protected BaseLoginProvider(
InstanceCrypto = instanceCrypto;
}

public virtual LoginProfile ProcessAuthoriztion(HttpContext context, IDictionary<string, string> @params)
public virtual LoginProfile ProcessAuthoriztion(HttpContext context, IDictionary<string, string> @params, IDictionary<string, string> additionalStateArgs = null)
{
try
{
var token = Auth(context, Scopes, out var redirect);
var token = Auth(context, Scopes, out var redirect, @params, additionalStateArgs);

if (redirect)
{
Expand All @@ -136,7 +136,7 @@ public virtual LoginProfile ProcessAuthoriztion(HttpContext context, IDictionary
}
}

protected virtual OAuth20Token Auth(HttpContext context, string scopes, out bool redirect, Dictionary<string, string> additionalArgs = null)
protected virtual OAuth20Token Auth(HttpContext context, string scopes, out bool redirect, IDictionary<string, string> additionalArgs = null, IDictionary<string, string> additionalStateArgs = null)
{
var error = context.Request.Query["error"];
if (!string.IsNullOrEmpty(error))
Expand All @@ -151,7 +151,7 @@ protected virtual OAuth20Token Auth(HttpContext context, string scopes, out bool
var code = context.Request.Query["code"];
if (string.IsNullOrEmpty(code))
{
context.Response.Redirect(OAuth20TokenHelper.RequestCode<T>(scopes, additionalArgs));
context.Response.Redirect(OAuth20TokenHelper.RequestCode<T>(scopes, additionalArgs, additionalStateArgs));
redirect = true;
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ public GosUslugiLoginProvider(
}


public override LoginProfile ProcessAuthoriztion(HttpContext context, IDictionary<string, string> @params)
public override LoginProfile ProcessAuthoriztion(HttpContext context, IDictionary<string, string> @params, IDictionary<string, string> additionalStateArgs = null)
{
try
{
Expand Down Expand Up @@ -142,7 +142,7 @@ public override LoginProfile ProcessAuthoriztion(HttpContext context, IDictionar
}
}

protected override OAuth20Token Auth(HttpContext context, string scopes, out bool redirect, Dictionary<string, string> additionalArgs = null)
protected override OAuth20Token Auth(HttpContext context, string scopes, out bool redirect, IDictionary<string, string> additionalArgs = null, IDictionary<string, string> additionalStateArgs = null)
{
var error = context.Request.Query["error"];
if (!string.IsNullOrEmpty(error))
Expand Down
2 changes: 1 addition & 1 deletion common/ASC.FederatedLogin/LoginProviders/ILoginProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ namespace ASC.FederatedLogin.LoginProviders
{
public interface ILoginProvider : IOAuthProvider
{
LoginProfile ProcessAuthoriztion(HttpContext context, IDictionary<string, string> @params);
LoginProfile ProcessAuthoriztion(HttpContext context, IDictionary<string, string> @params, IDictionary<string, string> additionalStateArgs);

LoginProfile GetLoginProfile(string accessToken);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public MailRuLoginProvider(
{
}

public override LoginProfile ProcessAuthoriztion(HttpContext context, IDictionary<string, string> @params)
public override LoginProfile ProcessAuthoriztion(HttpContext context, IDictionary<string, string> @params, IDictionary<string, string> additionalStateArgs = null)
{
try
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public OpenIdLoginProvider(Signature signature, InstanceCrypto instanceCrypto, C
ConsumerFactory = consumerFactory;
}

public LoginProfile ProcessAuthoriztion(HttpContext context, IDictionary<string, string> @params)
public LoginProfile ProcessAuthoriztion(HttpContext context, IDictionary<string, string> @params, IDictionary<string, string> additionalStateArgs = null)
{
var response = Openid.GetResponse();
if (response == null)
Expand Down
4 changes: 2 additions & 2 deletions common/ASC.FederatedLogin/LoginProviders/ProviderManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,9 @@ public ILoginProvider GetLoginProvider(string providerType)
: ConsumerFactory.GetByKey(providerType) as ILoginProvider;
}

public LoginProfile Process(string providerType, HttpContext context, IDictionary<string, string> @params)
public LoginProfile Process(string providerType, HttpContext context, IDictionary<string, string> @params, IDictionary<string, string> additionalStateArgs = null)
{
return GetLoginProvider(providerType).ProcessAuthoriztion(context, @params);
return GetLoginProvider(providerType).ProcessAuthoriztion(context, @params, additionalStateArgs);
}

public LoginProfile GetLoginProfile(string providerType, string accessToken)
Expand Down
4 changes: 2 additions & 2 deletions common/ASC.FederatedLogin/LoginProviders/VKLoginProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public VKLoginProvider(
}


public override LoginProfile ProcessAuthoriztion(HttpContext context, IDictionary<string, string> @params)
public override LoginProfile ProcessAuthoriztion(HttpContext context, IDictionary<string, string> @params, IDictionary<string, string> additionalStateArgs = null)
{
try
{
Expand All @@ -111,7 +111,7 @@ public override LoginProfile ProcessAuthoriztion(HttpContext context, IDictionar
{
{ "revoke", "1" }
}
: null);
: null, additionalStateArgs);

if (redirect)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public YandexLoginProvider(
{
}

public override LoginProfile ProcessAuthoriztion(HttpContext context, IDictionary<string, string> @params)
public override LoginProfile ProcessAuthoriztion(HttpContext context, IDictionary<string, string> @params, IDictionary<string, string> additionalStateArgs = null)
{
try
{
Expand All @@ -103,7 +103,7 @@ public override LoginProfile ProcessAuthoriztion(HttpContext context, IDictionar
{
{ "force_confirm", "true" }
}
: null);
: null, additionalStateArgs);
if (redirect)
{
return null;
Expand Down
15 changes: 10 additions & 5 deletions common/ASC.FederatedLogin/callback.htm
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@
<html>
<head>
<script language="javascript" type="text/javascript">
try {
window.opener.%CALLBACK%(%PROFILE%);
if (%DESKTOP%) {
localStorage.setItem("profile", %PROFILE%);
window.location.href = "/";
} else {
try {
window.opener.%CALLBACK%(%PROFILE%);
}
catch (ex) {
}
window.close();
}
catch (ex) {
}
window.close();
</script>
</head>
<body></body>
Expand Down
4 changes: 3 additions & 1 deletion packages/asc-web-common/store/AuthStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,11 @@ class AuthStore {

setWithCredentialsStatus(true);

this.reset();

this.init();

return Promise.resolve(true);
return Promise.resolve(this.settingsStore.defaultPage);
} catch (e) {
return Promise.reject(e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ class SectionBodyContent extends React.PureComponent {
};
loginCallback = (profile) => {
const { setProviders, t } = this.props;
linkOAuth(profile.Serialized).then((resp) => {
linkOAuth(profile).then((resp) => {
getAuthProviders().then((providers) => {
setProviders(providers);
toastr.success(t("ProviderSuccessfullyConnected"));
Expand Down
11 changes: 3 additions & 8 deletions products/ASC.People/Server/Controllers/PeopleController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1611,14 +1611,9 @@ public ICollection<AccountInfo> GetAuthProviders(bool inviteView, bool settingsV
{

var url = VirtualPathUtility.ToAbsolute("~/login.ashx") + $"?auth={provider}";
var mode = (settingsView || inviteView || (!MobileDetector.IsMobile() && !Request.DesktopApp())
? ("&mode=popup&callback=" + clientCallback)
: ("&mode=Redirect&returnurl="
+ HttpUtility.UrlEncode(new Uri(Request.GetUrlRewriter(),
"Auth.aspx"
+ (Request.DesktopApp() ? "?desktop=true" : "")
).ToString())
));
var mode = settingsView || inviteView || (!MobileDetector.IsMobile() && !Request.DesktopApp())
? $"&mode=popup&callback={clientCallback}"
: "&mode=Redirect&desktop=true";

infos.Add(new AccountInfo
{
Expand Down
16 changes: 12 additions & 4 deletions public/thirdparty/third-party.html
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,12 @@
const searchUrl = location.search.substring(1);
const object = JSON.parse(
'{"' +
decodeURIComponent(searchUrl)
.replace(/"/g, '\\"')
.replace(/&/g, '","')
.replace(/=/g, '":"') +
decodeURIComponent(
searchUrl
.replace(/"/g, '\\"')
.replace(/&/g, '","')
.replace(/=/g, '":"')
) +
'"}'
);

Expand All @@ -70,6 +72,8 @@
const urlParams = getObjectByLocation(window.location);
const code = urlParams ? urlParams.code || null : null;
const error = urlParams ? urlParams.error || null : null;
const desktop = urlParams ? urlParams.desktop || false : false;
const p = urlParams ? urlParams.p || false : false;
</script>
</head>
<body id="third-party-body">
Expand All @@ -78,6 +82,10 @@
<script>
if (code) {
localStorage.setItem("code", code);

if (desktop && p) {
window.location.href = `/login.ashx?p=${p}&code=${code}&desktop=true`;
}
} else if (error) {
renderError(error);
}
Expand Down
Loading

0 comments on commit 47d8fbc

Please sign in to comment.