コード例 #1
0
        public ISmartScopeOutcome ProcessScopes(PyroSearchParameters PyroSearchParameters, FHIRAllTypes ServiceResourceType, bool Read, bool Write)
        {
            ISmartScopeOutcome SmartScopeOutcome = new SmartScopeOutcome()
            {
                ScopesOK = false
            };

            // If FHIRApiAuthentication = false then no need to check and scopes, ScopesOK!
            if (!IGlobalProperties.FHIRApiAuthentication)
            {
                SmartScopeOutcome.ScopesOK = true;
                return(SmartScopeOutcome);
            }

            SmartEnum.Action SmartAction = GetActionEnum(Read, Write);

            if (System.Threading.Thread.CurrentPrincipal != null && System.Threading.Thread.CurrentPrincipal is ClaimsPrincipal Principal)
            {
                //Get Client Id, we need to log this somewere, maybe FHIR AuditEventy?
                System.Security.Claims.Claim ClientClaim = Principal.Claims.SingleOrDefault(x => x.Type == ClientIdName);

                //Get tye scopes
                List <System.Security.Claims.Claim> ScopeClaim = Principal.Claims.Where(x => x.Type == ScopeName).ToList();

                //This should be injected
                ScopeParse         ScopeParse = new ScopeParse();
                List <ISmartScope> ScopeList  = new List <ISmartScope>();
                foreach (var ScopeString in ScopeClaim)
                {
                    ISmartScope SmartScope = new SmartScope();
                    if (ScopeParse.Parse(ScopeString.Value, out SmartScope))
                    {
                        ScopeList.Add(SmartScope);
                    }
                    else
                    {
                        string Message = $"Unable to parse the SMART on FHIR scope given. Scope was {ScopeString.Value}";
                        var    OpOut   = Common.Tools.FhirOperationOutcomeSupport.Create(OperationOutcome.IssueSeverity.Error, OperationOutcome.IssueType.Exception, Message);
                        throw new Common.Exceptions.PyroException(System.Net.HttpStatusCode.InternalServerError, OpOut, Message);
                    }
                }

                IEnumerable <ISmartScope> FoundScopesList = ScopeList.Where(x => x.Resource == ServiceResourceType && (x.Action == SmartAction || x.Action == SmartEnum.Action.All));
                if (FoundScopesList.Count() > 0)
                {
                    if (PyroSearchParameters.IncludeList != null && PyroSearchParameters.IncludeList.Count > 0)
                    {
                        foreach (var Include in PyroSearchParameters.IncludeList)
                        {
                            FoundScopesList = ScopeList.Where(x => x.Resource == Include.SourceResourceType && (x.Action == SmartAction || x.Action == SmartEnum.Action.All));
                            if (FoundScopesList.Count() == 0)
                            {
                                //Reject
                                string Message = $"You do not have permission to access the {Include.SourceResourceType.GetLiteral()} Resource type found within your include or revinclude search parameters.";
                                var    OpOut   = Common.Tools.FhirOperationOutcomeSupport.Create(OperationOutcome.IssueSeverity.Error, OperationOutcome.IssueType.Forbidden, Message);
                                SmartScopeOutcome.OperationOutcome = OpOut;
                                SmartScopeOutcome.ScopesOK         = false;
                                return(SmartScopeOutcome);
                            }
                        }
                    }

                    var SearchParametersThatHaveChainParametersList = PyroSearchParameters.SearchParametersList.Where(x => x.ChainedSearchParameter != null);
                    if (SearchParametersThatHaveChainParametersList != null && SearchParametersThatHaveChainParametersList.Count() > 0)
                    {
                        foreach (ISearchParameterBase Chain in SearchParametersThatHaveChainParametersList)
                        {
                            string ResourceWithNoScopeAccess = RecursiveChainScoped(Chain, ScopeList, SmartAction);
                            if (!string.IsNullOrWhiteSpace(ResourceWithNoScopeAccess))
                            {
                                //Reject
                                string Message = $"You do not have permission to access {ResourceWithNoScopeAccess} resources types which was one of the resources types within your chained search parameter.";
                                var    OpOut   = Common.Tools.FhirOperationOutcomeSupport.Create(OperationOutcome.IssueSeverity.Error, OperationOutcome.IssueType.Forbidden, Message);
                                SmartScopeOutcome.OperationOutcome = OpOut;
                                SmartScopeOutcome.ScopesOK         = false;
                                return(SmartScopeOutcome);
                            }
                        }
                    }

                    //ALL GOOD! We have a scope for the resource and action. all ok.
                    SmartScopeOutcome.ScopesOK = true;
                    return(SmartScopeOutcome);
                }
                else
                {
                    string Message = string.Empty;
                    if (SmartAction == SmartEnum.Action.All)
                    {
                        Message = $"You do not have permission to access Resources {ServiceResourceType.GetLiteral()} types for Read or Write.";
                    }
                    else if (SmartAction == SmartEnum.Action.Read)
                    {
                        Message = $"You do not have permission to access Resources {ServiceResourceType.GetLiteral()} types for Read.";
                    }
                    else if (SmartAction == SmartEnum.Action.Read)
                    {
                        Message = $"You do not have permission to access Resources {ServiceResourceType.GetLiteral()} types for Write.";
                    }
                    var OpOut = Common.Tools.FhirOperationOutcomeSupport.Create(OperationOutcome.IssueSeverity.Error, OperationOutcome.IssueType.Forbidden, Message);
                    SmartScopeOutcome.OperationOutcome = OpOut;
                    SmartScopeOutcome.ScopesOK         = false;
                    return(SmartScopeOutcome);
                }
            }
            else
            {
                //System.Threading.Thread.CurrentPrincipal was null
                string Message = "Internal Server Error: System.Threading.Thread.CurrentPrincipal was null";
                var    OpOut   = Common.Tools.FhirOperationOutcomeSupport.Create(OperationOutcome.IssueSeverity.Error, OperationOutcome.IssueType.Exception, Message);
                throw new Common.Exceptions.PyroException(System.Net.HttpStatusCode.InternalServerError, OpOut, Message);
            }
        }
コード例 #2
0
        private static string GetScopeString(SmartEnum.Entity Entity, string Resource, SmartEnum.Action Action)
        {
            //user/*.write
            string ScopeString = string.Empty;

            if (Entity == SmartEnum.Entity.Patient)
            {
                ScopeString += KeyWord.Patient;
            }
            else if (Entity == SmartEnum.Entity.User)
            {
                ScopeString += KeyWord.User;
            }
            else
            {
                throw new FormatException($"Unkown Smart Scope Entity of {Entity.ToString()}");
            }

            ScopeString += KeyWord.SlashDelimiter;

            if (!String.IsNullOrWhiteSpace(Resource))
            {
                ScopeString += Resource;
            }
            else
            {
                throw new FormatException($"Unkown Smart Scope Resource of {Resource}");
            }

            ScopeString += KeyWord.DotDelimiter;

            if (Action == SmartEnum.Action.Read)
            {
                ScopeString += KeyWord.Read;
            }
            else if (Action == SmartEnum.Action.Write)
            {
                ScopeString += KeyWord.Write;
            }
            else if (Action == SmartEnum.Action.All)
            {
                ScopeString += KeyWord.All;
            }
            else
            {
                throw new FormatException($"Unkown Smart Scope Action of {Action.ToString()}");
            }

            return(ScopeString);
        }
コード例 #3
0
        private string RecursiveChainScoped(ISearchParameterBase ParentChain, List <ISmartScope> ScopeList, SmartEnum.Action SmartAction)
        {
            IEnumerable <ISmartScope> FoundScopesList = ScopeList.Where(x => x.Resource.GetLiteral() == ParentChain.Resource && (x.Action == SmartAction || x.Action == SmartEnum.Action.All));

            if (FoundScopesList.Count() > 0)
            {
                if (ParentChain.ChainedSearchParameter != null)
                {
                    //Test the next search parameter
                    return(RecursiveChainScoped(ParentChain.ChainedSearchParameter, ScopeList, SmartAction));
                }
                else
                {
                    //If the scopes are fine and allowed then we return empty string as suscess
                    return(string.Empty);
                }
            }
            else
            {
                //If we are unable to find a scope for a given resource type we return the Resource name for error reporting.
                return(ParentChain.Resource);
            }
        }
コード例 #4
0
 //Support Methods
 private static string[] GetAllResourcesScopeStringList(SmartEnum.Entity Entity, SmartEnum.Action Action)
 {
     string[] ScopeList = new string[ModelInfo.SupportedResources.Count];
     for (int i = 0; i < ModelInfo.SupportedResources.Count; i++)
     {
         ScopeList[i] = GetScopeString(Entity, ModelInfo.SupportedResources[i], Action);
     }
     return(ScopeList);
 }