Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • Experimental/newSaml2
  • Fix/xxxx-migrateLogin
  • Hotfix/1234-handlingMergeToken
  • Hotfix/1354-workingFHLogin
  • Hotfix/1357-ymlFile
  • Hotfix/1370-swaggerDescription
  • Hotfix/1545-emptyUserGraphs
  • Hotfix/2087-efNet6
  • Hotfix/2103-RepositoryurlstoConsulUpdateMappingGivennameDev
  • Hotfix/2103-RepositoryurlstoConsulUpdateMappingGivennameUiv2
  • Hotfix/2169-ignoreAuthContext
  • Hotfix/2576-certificatePatch
  • Hotfix/2592-sameProvider
  • Hotfix/2775-dfnCertRollover
  • Hotfix/64-releaseUDE
  • Issue/1833-newLogin
  • Issue/1910-MigrationtoNET6.0
  • Issue/1964-tokenExpiryUIv2
  • Issue/1974-shibbolethLogout
  • Issue/2078-renamingEntitlementAcceptStaff
  • Issue/2078-renamingEntitlementAcceptStaffUiv2
  • Issue/2115-extendParsingPairwiseId
  • Issue/2147-exchangingCoscineCertificate
  • Issue/2147-exchangingCoscineCertificate-step2
  • Issue/2147-exchangingCoscineCertificate-step3
  • Issue/2309-docs
  • Issue/2325-fixApiTokenMerging
  • Issue/3003-stsInstitute
  • Issue/40-rdsQuotaForUKA
  • Product/1149-dfnaai
  • Product/1287-dotnet5Sharepoint
  • Product/1290-dfnaai
  • Product/1414-fhPrivileges
  • Product/1629-onboardingOtherUniversities
  • Product/797-overhaul
  • Product/917-maintenanceFunctionality
  • Sprint/2020-20
  • Sprint/2020-21
  • Sprint/2020-22
  • Sprint/2021-01
  • Sprint/2021-03
  • Sprint/2021-05
  • Sprint/2021-06
  • Sprint/2021-08
  • Sprint/2021-10
  • Sprint/2021-11
  • Sprint/2021-19
  • Sprint/2021-20
  • Sprint/2021-23
  • Sprint/2022-01
  • Topic/1224-overhaul
  • Topic/1276-DFN-AAIFrontend
  • Topic/1278-dfnAAI
  • Topic/1297-maintenanceBanner
  • Topic/1335-dotnet5Apis
  • Topic/1425-fhPrivileges
  • Topic/1711-extendResourceTypeConfiguration
  • dev
  • gitkeep
  • master
  • top
  • uiv2
  • v1.0.0
  • v1.1.0
  • v1.10.0
  • v1.10.1
  • v1.10.2
  • v1.11.0
  • v1.11.1
  • v1.11.2
  • v1.11.3
  • v1.12.0
  • v1.13.0
  • v1.14.0
  • v1.14.1
  • v1.15.0
  • v1.16.0
  • v1.16.1
  • v1.16.2
  • v1.17.0
  • v1.18.0
  • v1.2.0
  • v1.2.1
  • v1.3.0
  • v1.4.0
  • v1.5.0
  • v1.6.0
  • v1.7.0
  • v1.8.0
  • v1.8.1
  • v1.9.0
  • v1.9.1
  • v2.0.0
  • v2.0.1
  • v2.0.2
  • v2.0.3
  • v2.1.0
  • v2.2.0
  • v2.2.1
  • v2.2.2
  • v2.2.3
  • v2.2.4
  • v2.3.0
  • v2.3.1
  • v2.3.2
  • v2.3.3
  • v2.4.0
  • v2.4.1
  • v2.4.2
  • v2.4.3
  • v2.4.4
  • v3.0.0
  • v3.1.0
  • v3.1.1
  • v3.1.2
  • v3.1.3
  • v3.1.4
  • v4.0.0
  • v4.0.1
  • v4.0.2
  • v4.0.3
  • v4.0.4
  • v4.0.5
  • v4.0.6
  • v4.0.7
  • v4.0.8
  • v4.0.9
  • v4.1.0
  • v4.1.1
129 results

Target

Select target project
  • coscine/backend/apis/sts
1 result
Select Git revision
Show changes
Commits on Source (4)
using Coscine.Api.STS.Models;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using Coscine.Api.STS.Data;
using Coscine.Api.STS.Models;
using Coscine.Api.STS.Utils;
using Coscine.Api.STS.Data;
using Microsoft.AspNetCore.Identity;
using System;
using Microsoft.AspNetCore.Mvc;
using System.Linq;
using Newtonsoft.Json;
using System.Threading.Tasks;
namespace Coscine.Api.STS.Controllers
{
......@@ -19,18 +17,24 @@ namespace Coscine.Api.STS.Controllers
_signInManager = signInManager;
}
[Route("[controller]/login")]
public ActionResult Login(string returnUrl)
/// <summary>
/// Return relevant URLs for logging the user in
/// </summary>
/// <returns>Return relevant URLs for logging the user in</returns>
[HttpGet("[controller]/urls/login")]
public ActionResult<LoginUrls> GetLoginUrls()
{
ViewBag.ReturnUrl = UrlGenerator.ExtendReturnUrl(returnUrl, Request);
ViewBag.ORCiDUrl = ORCiDHandler.GetORCiDOAuthUrl() + UrlGenerator.ORCiDRedirectUrl();
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
ViewBag.AppJs = enc.GetString(Program.Configuration.GetAndWait("coscine/apps/login/appjs"));
ViewBag.IdentityProviders = JsonConvert.SerializeObject(Startup.CurrentSaml2Options?.
IdentityProviders.KnownIdentityProviders.Select((idp) => idp.EntityId));
return View();
return new LoginUrls
{
OrcidUrl = ORCiDHandler.GetORCiDOAuthUrl() + UrlGenerator.ORCiDRedirectUrl(),
IdentityProviders = Startup.CurrentSaml2Options?.IdentityProviders.KnownIdentityProviders.Select((idp) => idp.EntityId)
};
}
/// <summary>
/// Route for logging the user out of Coscine
/// </summary>
/// <returns>Redirects the user back to the login page</returns>
[Route("[controller]/logout")]
public async Task<ActionResult> Logout()
{
......@@ -47,13 +51,14 @@ namespace Coscine.Api.STS.Controllers
}
}
ViewBag.LoginUrl = UrlGenerator.GetLoginUrl(Request) + "&logout=true";
ViewBag.LoginUrl = UrlGenerator.GetLoginUrl(Request) + "?logout=true";
if (loggedInWithShibboleth)
{
ViewBag.LoginUrl += "&loggedInWithShibboleth=true";
}
return View();
return Redirect(ViewBag.LoginUrl);
}
}
}
using System;
using System.Security.Claims;
using Microsoft.AspNetCore.Mvc;
using Coscine.ActiveDirectory;
using Coscine.Api.STS.Utils;
using Coscine.ApiCommons;
using Coscine.Database.Models;
using Coscine.JwtHandler;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using Coscine.ActiveDirectory;
using System.Net.Http;
using System.Collections.Generic;
using Coscine.JwtHandler;
using System.Security.Claims;
namespace Coscine.Api.STS.Controllers
{
......@@ -16,6 +16,10 @@ namespace Coscine.Api.STS.Controllers
{
private static readonly HttpClient _httpClient = new();
/// <summary>
/// The controller that the user is automatically entering when accesing the route .../coscine/api/Coscine.STS/
/// </summary>
/// <returns>Redirecting</returns>
[Route("/")]
public ActionResult Index()
{
......@@ -29,23 +33,28 @@ namespace Coscine.Api.STS.Controllers
string mergeCallbackUrl = UrlGenerator.MergeCallbackRedirectUrl();
return Redirect(mergeCallbackUrl);
}
if (!AreTOSAccepted(userId))
{
string tosUrl = UrlGenerator.GetTOSUrl(Request, userIdString);
return Redirect(tosUrl);
}
ProcessSignIn(User);
var redirects = Request.Query["redirect"];
if (redirects.Count > 0)
// Process where the user will be redirected to
if (!AreTOSAccepted(userId))
{
ViewBag.Redirect = redirects[0];
// Will redirect to the ToS page
ViewBag.Redirect = UrlGenerator.GetTOSUrl(Request);
}
else
{
ViewBag.Redirect = "/";
var redirects = Request.Query["redirect"];
if (redirects.Count > 0)
{
// Will redirect to the desired redirect location
ViewBag.Redirect = redirects[0];
}
else
{
// Will redirect to root/home page
ViewBag.Redirect = "/";
}
}
var dictionary = new Dictionary<string, string>
......@@ -56,22 +65,22 @@ namespace Coscine.Api.STS.Controllers
ViewBag.Token = jwtHandler.GenerateJwtToken(dictionary);
// STS Exit Point
return View();
return View(); // Adds token to local storage and redirects
}
string loginUrl = UrlGenerator.GetLoginUrl(Request);
return Redirect(loginUrl);
}
private bool AreTOSAccepted(Guid userId)
private static bool AreTOSAccepted(Guid userId)
{
TOSModel tosModel = new TOSModel();
var tosModel = new TOSModel();
var tosAcceptedList = tosModel.GetAllWhere((entry) => entry.UserId == userId);
var currentTos = Configurator.Configuration.GetStringAndWait("coscine/global/tos/version");
return tosAcceptedList != null
&& tosAcceptedList.Any((entry) => entry.Version == currentTos);
}
private void ProcessSignIn(ClaimsPrincipal user)
private static void ProcessSignIn(ClaimsPrincipal user)
{
var userModel = new UserModel();
var realUser = userModel.GetById(Guid.Parse(user.Identity.Name));
......
using Coscine.Database.DataModel;
using Coscine.Api.STS.Data;
using Coscine.Api.STS.Models;
using Coscine.Api.STS.Utils;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using System.Security.Claims;
using Coscine.Database.DataModel;
using Coscine.Database.Models;
using System.Linq;
using Coscine.Api.STS.Data;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
#region DupFinder Exclusion
namespace Coscine.Api.STS.Controllers
......@@ -21,13 +21,24 @@ namespace Coscine.Api.STS.Controllers
_signInManager = signInManager;
}
/// <summary>
/// ORCiD Login Route
/// </summary>
/// <param name="returnUrl">URL to be redirected to</param>
/// <returns>Route that is necessary to parse the hashed ORCiD data</returns>
[Route("[controller]/login")]
public ActionResult Login(string returnUrl)
{
ViewBag.ReturnUrl = UrlGenerator.ExtendReturnUrl(returnUrl, Request);
return View();
}
/// <summary>
/// Execute ORCiD validation and login
/// </summary>
/// <param name="model">ORCiD Model after successful parsing</param>
/// <param name="returnUrl">URL to be redirected to</param>
/// <returns></returns>
[HttpPost("[controller]/login")]
public async Task<ActionResult> Login(ORCiDModel model, string returnUrl)
{
......
......@@ -23,6 +23,13 @@ namespace Coscine.Api.STS.Controllers
_rdfStoreConnector = new RdfStoreConnector(Program.Configuration.GetString("coscine/local/virtuoso/additional/url"));
}
/// <summary>
/// Callback method to catch the login
/// </summary>
/// <param name="returnUrl">URL to be redirected to</param>
/// <param name="remoteError">Erros on remote login</param>
/// <returns>Redirect</returns>
/// <exception cref="ArgumentException"></exception>
[Route("[controller]/callback")]
public async Task<ActionResult> Callback(string returnUrl = null, string remoteError = null)
{
......@@ -128,6 +135,7 @@ namespace Coscine.Api.STS.Controllers
result = await _signInManager.UserManager.AddLoginAsync(coscineUser, info);
await _signInManager.SignInAsync(coscineUser, isPersistent: false);
returnUrl = Program.MainUrl + "/?redirect=" + ((returnUrl != null) ? Uri.EscapeDataString(returnUrl) : "");
return Redirect(UrlGenerator.ExtendReturnUrl(returnUrl, Request));
}
......@@ -136,14 +144,14 @@ namespace Coscine.Api.STS.Controllers
/// On default, the user is redirected to the WAFY of the DFN-AAI.
/// Setting the "entityId" parameter allows the application to redirect to a specific identity provider defined by DFN-AAI.
/// </summary>
/// <param name="returnUrl"></param>
/// <param name="returnUrl">URL to be redirected to</param>
/// <param name="entityId">Specific Identitiy Provider to be redirect to</param>
/// <returns>ChallengeResult</returns>
[Route("[controller]/login")]
public ActionResult Login(string returnUrl, string entityId = null)
public ActionResult Login(string returnUrl = null, string entityId = null)
{
var provider = "Saml2";
var redirectUrl = Program.MainUrl + "/Shibboleth/Callback?returnUrl=" + returnUrl;
var redirectUrl = Program.MainUrl + "/Shibboleth/callback?returnUrl=" + returnUrl;
redirectUrl = UrlGenerator.ExtendReturnUrl(redirectUrl, Request);
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
if (entityId != null)
......@@ -153,4 +161,4 @@ namespace Coscine.Api.STS.Controllers
return new ChallengeResult(provider, properties);
}
}
}
}
\ No newline at end of file
using System.Collections.Generic;
namespace Coscine.Api.STS.Models;
public class LoginUrls
{
public string OrcidUrl { get; set; } = null!;
public IEnumerable<Sustainsys.Saml2.Metadata.EntityId> IdentityProviders { get; set; } = null!;
}
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations;
namespace Coscine.Api.STS.Models
namespace Coscine.Api.STS.Models;
public class ORCiDModel
{
public class ORCiDModel
{
[Required]
[Display(Name = "ORCiD_JWT")]
public string ORCiD_JWT { get; set; }
}
[Required]
[Display(Name = "ORCiD_JWT")]
public string ORCiD_JWT { get; set; }
}
using Coscine.ApiCommons;
using Coscine.Configuration;
using System.Net;
using System.Text;
namespace Coscine.Api.STS
......
......@@ -6,7 +6,7 @@
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<TargetFramework>net6.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<Version>3.1.4</Version>
<Version>4.0.0</Version>
</PropertyGroup>
<PropertyGroup>
<Authors>RWTH Aachen University</Authors>
......@@ -25,6 +25,7 @@
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="6.0.4" />
<PackageReference Include="Microsoft.IdentityModel.Tokens.Saml" Version="6.17.0" />
<PackageReference Include="NSwag.AspNetCore" Version="13.17.0" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
......
using Coscine.ApiCommons;
using Coscine.Api.STS.Data;
using Coscine.Api.STS.Data;
using Coscine.Api.STS.Utils;
using Coscine.ApiCommons;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using NSwag;
using NSwag.Generation.Processors.Security;
using Sustainsys.Saml2;
using Sustainsys.Saml2.Metadata;
using System;
using Sustainsys.Saml2.AspNetCore2;
using System.Security.Cryptography.X509Certificates;
using Sustainsys.Saml2.Metadata;
using Sustainsys.Saml2.Metadata.Services;
using System;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
namespace Coscine.Api.STS
{
......@@ -22,12 +26,20 @@ namespace Coscine.Api.STS
/// so that the IdentityProviders and other entries can be accessed.
/// </summary>
public static Saml2Options CurrentSaml2Options;
private ApplicationInformation _applicationInformation;
public Startup()
{
}
public override void SetBasePath(ApplicationInformation applicationInformation)
{
base.SetBasePath(applicationInformation);
_applicationInformation = applicationInformation;
}
public override void ConfigureServicesExtensionLate(IServiceCollection services)
{
base.ConfigureServicesExtensionLate(services);
......@@ -102,6 +114,34 @@ namespace Coscine.Api.STS
// For dealing with `'DeclarationReference' must be an absolute Uri``
options.SPOptions.Compatibility.IgnoreAuthenticationContextInResponse = true;
});
// Register the Swagger services
services.AddOpenApiDocument((settings) =>
{
settings.Title = _applicationInformation.AppName;
settings.Version = _applicationInformation.Version.ToString();
settings.PostProcess = (postProcess) =>
{
postProcess.Host = _applicationInformation.ApiUrl;
};
settings.OperationProcessors.Add(new OperationSecurityScopeProcessor("JWT token"));
settings.DocumentProcessors.Add(new SecurityDefinitionAppender("JWT token", new OpenApiSecurityScheme
{
Type = OpenApiSecuritySchemeType.ApiKey,
Name = "Authorization",
Description = "Copy 'Bearer ' + valid JWT token into field",
In = OpenApiSecurityApiKeyLocation.Header
}));
});
}
public override void ConfigureExtensionLate(IApplicationBuilder app, IWebHostEnvironment env)
{
base.ConfigureExtensionLate(app, env);
app.UseStaticFiles();
app.UseOpenApi();
app.UseSwaggerUi3();
}
}
}
\ No newline at end of file
using Microsoft.IdentityModel.Tokens;
using Coscine.Api.STS.Models;
using Microsoft.IdentityModel.Tokens;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Net;
using System.Net.Http;
using System.Security.Claims;
using System.Text.Json;
namespace Coscine.Api.STS.Utils
{
public class ORCiDHandler
{
public static readonly string _loginStatusUrl = "https://orcid.org/userStatus.json";
public static string GetORCiDOAuthUrl()
{
return Program.Configuration.GetStringAndWait("coscine/global/orcid/url")
......
using Coscine.JwtHandler;
using Microsoft.AspNetCore.Http;
using System.Collections.Generic;
using System.Net;
namespace Coscine.Api.STS.Utils
{
/// <summary>
/// URL Generator Helper methods
/// </summary>
public class UrlGenerator
{
/// <summary>
/// Login URL for Coscine
/// </summary>
/// <param name="request">HttpRequest from the context</param>
/// <returns>Complete login URL for the host machine</returns>
public static string GetLoginUrl(HttpRequest request)
{
var query = request.Query;
......@@ -15,20 +22,19 @@ namespace Coscine.Api.STS.Utils
{
addedEntries += "&" + queryEntry.Key + "=" + queryEntry.Value;
}
var loginUrl = Program.MainUrl + "/account/login?ReturnUrl=" + WebUtility.UrlEncode(Program.MainUrl) + addedEntries;
var loginUrl = Program.HostUrl + "/login/";
return loginUrl;
}
public static string GetTOSUrl(HttpRequest request, string userId)
/// <summary>
/// Terms of Service URL for Coscine
/// </summary>
/// <param name="request">HttpRequest from the context</param>
/// <returns></returns>
public static string GetTOSUrl(HttpRequest request)
{
var queryString = GetLoginUrl(request);
var jwtHandler = new JWTHandler(Program.Configuration);
var dictionary = new Dictionary<string, string>
{
{ "UserId", userId }
};
var token = jwtHandler.GenerateJwtToken(dictionary);
return queryString + "&tos=true&jwt=" + token;
return queryString + "tos";
}
public static string ExtendReturnUrl(string returnUrl, HttpRequest request)
......@@ -52,17 +58,17 @@ namespace Coscine.Api.STS.Utils
public static string ORCiDRedirectUrl()
{
return Program.MainUrl + "/orcid/login?ReturnUrl=" + Program.MainUrl;
return Program.MainUrl + "/orcid/login?returnUrl=" + Program.MainUrl;
}
public static string ShibbolethRedirectUrl()
{
return Program.MainUrl + "/shibboleth/login?ReturnUrl=" + Program.MainUrl;
return Program.MainUrl + "/shibboleth/login?returnUrl=" + Program.MainUrl;
}
public static string MergeCallbackRedirectUrl()
{
return Program.MainUrl + "/merge/callback?ReturnUrl=" + Program.MainUrl;
return Program.MainUrl + "/merge/callback?returnUrl=" + Program.MainUrl;
}
}
}
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<title>Login - Coscine</title>
<script src="/coscine/apps/i18n/js/app.js"></script>
</head>
<body class="fullwidth">
<div
id="loginpage"
returnUrl="@ViewBag.ReturnUrl"
orcidUrl="@ViewBag.ORCiDUrl"
identitiyProviders="@ViewBag.IdentityProviders">
</div>
<script src="@ViewBag.AppJs"></script>
<!--[if lt IE 9]>
<button
id="orcidbutton"
name="getORCiDForm"
class="btn btn-primary w-100"
>
<span>
<img
alt="ORCID logo"
id="orcid-id-logo"
src="https://orcid.org/sites/default/files/images/orcid_24x24.png"
width="25"
height="25"
/>
</span>
<span> Sign in with ORCID ID</span>
</button>
<br>
<br>
<form action="/coscine/api/Coscine.Api.STS/Shibboleth/login?returnUrl=@ViewBag.ReturnUrl" method="post">
<input type="submit" id="guidbutton" value="Sign in using Shibboleth"></input>
<input type="hidden" name="wa" value="wsignin1.0" />
</form>
<script type="text/javascript">
function getORCiDUrl() {
var hookupElement = document.getElementById('loginpage');
var orcidUrlString =
(hookupElement != null ? hookupElement.getAttribute('orcidUrl') : '');
var orcidUrl = encodeURI(orcidUrlString);
return orcidUrl;
}
document.getElementById('orcidbutton').onclick = function(event) {
window.location.href = getORCiDUrl();
};
</script>
<![endif]-->
</body>
</html>
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<title>Logout - Coscine</title>
<script type="text/javascript">
var storedKeys = Object.keys(localStorage);
for (var i = 0; i < storedKeys.length; i++) {
if (storedKeys[i] !== 'coscine.login.storedData') {
localStorage.removeItem(storedKeys[i]);
}
};
sessionStorage.clear();
window.location.href = "@Html.Raw(ViewBag.LoginUrl)";
</script>
<script src="/coscine/apps/i18n/js/app.js"></script>
</head>
<body>
</body>
</html>