Skip to content
Snippets Groups Projects
Select Git revision
  • db5050c66df3525a2625dd0429e3167c59111b60
  • main default protected
  • gitkeep
  • dev protected
  • Issue/2914-trellisMigrator
  • Issue/2847-reporting
  • Hotfix/2776-workingNewVersion
  • Hotfix/xxxx-correctAssignments
  • Issue/2666-adminCronjobs-theSequal
  • Issue/2666-adminCronjobs
  • Issue/2518-docs
  • Hotfix/xxxx-coscineGraph
  • Issue/2304-virtuosoRoars
  • Fix/v0.1.7-dependencies
  • Hotfix/2212-fixFiles
  • Issue/2222-resourceDateCreated
  • Issue/2221-projectDateCreated
  • Hotfix/xxxx-changeUrls
  • Issue/1321-pidEnquiryOverhaul
  • Issue/1782-structualDataIntegration
  • Issue/2084-migrateResourceStructuralData
  • v0.1.24
  • v0.1.23
  • v0.1.22
  • v0.1.21
  • v0.1.20
  • v0.1.19
  • v0.1.18
  • v0.1.17
  • v0.1.16
  • v0.1.15
  • v0.1.14
  • v0.1.13
  • v0.1.12
  • v0.1.11
  • v0.1.10
  • v0.1.9
  • v0.1.7
  • v0.1.8
  • v0.1.6
  • v0.1.5
41 results

ResourceStructuralData.cs

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    ShibbolethController.cs 6.68 KiB
    using Coscine.Api.STS.Data;
    using Coscine.Api.STS.Utils;
    using Coscine.Database.DataModel;
    using Coscine.Database.Models;
    using Coscine.Metadata;
    using Microsoft.AspNetCore.Identity;
    using Microsoft.AspNetCore.Mvc;
    using System;
    using System.Linq;
    using System.Security.Claims;
    using System.Threading.Tasks;
    
    namespace Coscine.Api.STS.Controllers
    {
        public class ShibbolethController : Controller
        {
            private readonly SignInManager<CoscineUser> _signInManager;
            private readonly RdfStoreConnector _rdfStoreConnector;
    
            public ShibbolethController(SignInManager<CoscineUser> signInManager)
            {
                _signInManager = signInManager;
                _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)
            {
                if (remoteError != null)
                {
                    throw new ArgumentException($"Error from external provider: {remoteError}");
                }
    
                var info = await _signInManager.GetExternalLoginInfoAsync();
                if (info == null)
                {
                    return Redirect(UrlGenerator.GetLoginUrl(Request));
                }
     
                var externalAuthenticatorModel = new ExternalAuthenticatorModel();
                var shibbolethAuthItem = externalAuthenticatorModel.GetWhere((externalAuthenticator) => externalAuthenticator.DisplayName == "Shibboleth");
    
                var externalIdModel = new ExternalIdModel();
                var entity = info.Principal.FindFirstValue(ShibbolethAttributeMapping.Identifier);
    
                if (string.IsNullOrWhiteSpace(entity))
                {
                    entity = info.Principal.FindFirstValue(ShibbolethAttributeMapping.PairwiseID);
                }
    
                var identifier = "";
                var entityId = "";
                if (entity.IndexOf(">") > -1)
                {
                    identifier = entity[(entity.IndexOf(">") + 1)..];
                    identifier = identifier.Substring(0, identifier.IndexOf("<"));
    
                    entityId = entity[(entity.IndexOf("NameQualifier=\"") + "NameQualifier=\"".Length)..];
                    entityId = entityId.Substring(0, entityId.IndexOf("\""));
                }
                else
                {
                    identifier = entity;
                    entityId = info.AuthenticationProperties.Items["idp"];
                }
    
                var mapping = externalIdModel.GetAllWhere((map) =>
                    map.ExternalId1 == identifier
                    && map.ExternalAuthenticatorId == shibbolethAuthItem.Id
                    && map.Organization == entityId
                );
                User user;
                var userModel = new UserModel();
                if (mapping.Any())
                {
                    var userId = mapping.First().UserId;
                    user = userModel.GetById(userId);
                }
                else
                {
                    user = ShibbolethAttributeMapping.CreateUser(info.Principal);
                    userModel.Insert(user);
                    externalIdModel.Insert(new ExternalId
                    {
                        ExternalId1 = identifier,
                        ExternalAuthenticatorId = shibbolethAuthItem.Id,
                        Organization = entityId,
                        UserId = user.Id
                    });
                }
    
                var userGraphName = $"{_rdfStoreConnector.UserUrlPrefix}/{user.Id}";
    
                // Make sure the user graph exists.
                _rdfStoreConnector.EnsureGraph(userGraphName);
    
                // Get organization.
                var organization = _rdfStoreConnector.GetOrganization(entityId, identifier);
    
                // Can only update data if an org was found.
                if (organization != null)
                {
                    // Drop old membership infromation.
                    _rdfStoreConnector.RemoveMembershipData(userGraphName, organization);
    
                    // Reverse lookup...
                    var eduPersonScopedAffiliation = info.Principal.FindAll(ShibbolethAttributeMapping.LabelMapping.FirstOrDefault(x => x.Value == "ScopedAffiliation").Key);
                    var orgFromId = _rdfStoreConnector.GetOrgnizationWithIdentifier(identifier);
                    if (eduPersonScopedAffiliation.Any(x => x.Value.StartsWith("employee@") || x.Value.StartsWith("staff@")))
                    {
                        // Add membership information.
                        _rdfStoreConnector.AddMemebershipData(userGraphName, organization);
                    }
                    else if (orgFromId != null)
                    {
                        // Add membership information.
                        _rdfStoreConnector.AddMemebershipData(userGraphName, orgFromId);
                    }
                }
    
                var coscineUser = new CoscineUser()
                {
                    UserName = user.Id.ToString(),
                    Email = user.EmailAddress ?? ""
                };
    
                var result = await _signInManager.UserManager.CreateAsync(coscineUser);
                result = await _signInManager.UserManager.AddLoginAsync(coscineUser, info);
                await _signInManager.SignInAsync(coscineUser, isPersistent: false);
    
                return Redirect(UrlGenerator.ExtendReturnUrl(returnUrl, Request));
            }
    
            /// <summary>
            /// This method is the central route for logging into an identity provider.
            /// 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">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)
            {
                var provider = "Saml2";
                var redirectUrl = Program.MainUrl + "/Shibboleth/callback?returnUrl=" + returnUrl;
                redirectUrl = UrlGenerator.ExtendReturnUrl(redirectUrl, Request);
                var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
                if (entityId != null)
                {
                    properties.Items.Add("idp", entityId);
                }
                return new ChallengeResult(provider, properties);
            }
        }
    }