示例#1
0
        private async Task <IEnumerable <string> > GetProviderFilterForClientAsync(SignInMessage message)
        {
            IEnumerable <string> filter = null;

            if (!String.IsNullOrWhiteSpace(message.ClientId))
            {
                var client = await _clientStore.FindClientByIdAsync(message.ClientId);

                if (client == null)
                {
                    throw new InvalidOperationException("Invalid client: " + message.ClientId);
                }
                filter = client.IdentityProviderRestrictions ?? filter;
            }
            filter = filter ?? Enumerable.Empty <string>();
            return(filter);
        }
        public virtual async Task <System.IO.Stream> Login(LoginViewModel model, SignInMessage message)
        {
            var client = await _clientStore.FindClientByIdAsync(message.ClientId);

            var name = client?.ClientName;

            return(await Render(model, "login", name));
        }
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            var source = serializer.Deserialize <ClientModel>(reader);

            var client = _clientStore.FindClientByIdAsync(source.ClientId).GetAwaiter().GetResult();

            return(client);
        }
示例#4
0
        public async Task Invalid_GrantType_For_Client()
        {
            var client = await _clients.FindClientByIdAsync("client");

            var validator = Factory.CreateTokenValidator();

            var parameters = new NameValueCollection();

            parameters.Add(Constants.TokenRequest.GrantType, "assertionType");
            parameters.Add(Constants.TokenRequest.Assertion, "assertion");
            parameters.Add(Constants.TokenRequest.Scope, "resource");

            var result = await validator.ValidateRequestAsync(parameters, client);

            Assert.IsTrue(result.IsError);
            Assert.AreEqual(Constants.TokenErrors.UnauthorizedClient, result.Error);
        }
        /// <summary>
        /// Gets the currently running client app to put it's name in the login page
        /// </summary>
        /// <param name="model"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public async Task <Stream> Login(LoginViewModel model, SignInMessage message)
        {
            var client = await clientStore.FindClientByIdAsync(message.ClientId);

            var name = client != null ? client.ClientName : null;

            return(await Render(model, "login", name));
        }
        public virtual async Task <System.IO.Stream> Login(IDictionary <string, object> env, LoginViewModel model, SignInMessage message)
        {
            var client = await clientStore.FindClientByIdAsync(message.ClientId);

            var name = client != null ? client.ClientName : null;

            return(await Render(model, "login", name));
        }
        public async Task <IActionResult> Callback()
        {
            // read external identity from the temporary cookie
            var result = await HttpContext.AuthenticateAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme);

            if (result?.Succeeded != true)
            {
                throw new Exception("External authentication error");
            }

            // lookup our user and external provider info
            var(user, provider, providerUserId, claims) = FindUserFromExternalProvider(result);
            if (user == null)
            {
                // this might be where you might initiate a custom workflow for user registration
                // in this sample we don't show how that would be done, as our sample implementation
                // simply auto-provisions new external user
                user = AutoProvisionUser(provider, providerUserId, claims);
            }

            // this allows us to collect any additonal claims or properties
            // for the specific prtotocols used and store them in the local auth cookie.
            // this is typically used to store data needed for signout from those protocols.
            var additionalLocalClaims = new List <Claim>();
            var localSignInProps      = new AuthenticationProperties();

            ProcessLoginCallbackForOidc(result, additionalLocalClaims, localSignInProps);
            ProcessLoginCallbackForWsFed(result, additionalLocalClaims, localSignInProps);
            ProcessLoginCallbackForSaml2p(result, additionalLocalClaims, localSignInProps);

            // issue authentication cookie for user
            await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.SubjectId, user.Username));

            await HttpContext.SignInAsync(user.SubjectId, user.Username, provider, localSignInProps, additionalLocalClaims.ToArray());

            // delete temporary cookie used during external authentication
            await HttpContext.SignOutAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme);

            // retrieve return URL
            var returnUrl = result.Properties.Items["returnUrl"] ?? "~/";

            // check if external login is in the context of an OIDC request
            var context = await _interaction.GetAuthorizationContextAsync(returnUrl);

            if (context != null)
            {
                if (await _clientStore.FindClientByIdAsync(context.ClientId) != null)
                {
                    // if the client is PKCE then we assume it's native, so this change in how to
                    // return the response is for better UX for the end user.
                    return(View("Redirect", new RedirectViewModel {
                        RedirectUrl = returnUrl
                    }));
                }
            }

            return(Redirect(returnUrl));
        }
        public async Task Non_existing_RefreshToken()
        {
            var store  = new InMemoryRefreshTokenStore();
            var client = await _clients.FindClientByIdAsync("roclient");

            var validator = Factory.CreateTokenValidator(
                refreshTokens: store);

            var parameters = new NameValueCollection();

            parameters.Add(Constants.TokenRequest.GrantType, "refresh_token");
            parameters.Add(Constants.TokenRequest.RefreshToken, "nonexistent");

            var result = await validator.ValidateRequestAsync(parameters, client);

            Assert.IsTrue(result.IsError);
            Assert.AreEqual(Constants.TokenErrors.InvalidGrant, result.Error);
        }
        /// <summary>
        /// Finds a client by id
        /// </summary>
        /// <param name="clientId">The client id</param>
        /// <returns>
        /// The client
        /// </returns>
        public async Task <Client> FindClientByIdAsync(string clientId)
        {
            var client = await _cache.GetAsync(clientId,
                                               _options.Caching.ClientStoreExpiration,
                                               async() => await _inner.FindClientByIdAsync(clientId),
                                               _logger);

            return(client);
        }
示例#10
0
        /// <summary>
        /// Finds a client by id
        /// </summary>
        /// <param name="clientId">The client id</param>
        /// <returns>
        /// The client
        /// </returns>
        public async Task <Client> FindClientByIdAsync(string clientId)
        {
            var key    = $"{_scopedTenantRequestContext.Context.TenantName}.{clientId}";
            var client = await _cache.GetAsync(key,
                                               _options.Caching.ClientStoreExpiration,
                                               () => _inner.FindClientByIdAsync(clientId),
                                               _logger);

            return(client);
        }
        public virtual async Task <System.IO.Stream> Login(LoginViewModel model, SignInMessage message)
        {
            var client = await clientStore.FindClientByIdAsync(message.ClientId);

            var name = client != null ? client.ClientName : null;

            //model.Custom = new { customMessage = "Hello World!" };
            model.Custom = message.Tenant;
            return(await Render(model, "login", name));
        }
示例#12
0
        /// <summary>
        /// Custom validation logic for access tokens.
        /// </summary>
        /// <param name="result">The validation result so far.</param>
        /// <returns>
        /// The validation result
        /// </returns>
        public virtual async Task <TokenValidationResult> ValidateAccessTokenAsync(TokenValidationResult result)
        {
            if (result.IsError)
            {
                return(result);
            }

            // make sure user is still active (if sub claim is present)
            var subClaim = result.Claims.FirstOrDefault(c => c.Type == Constants.ClaimTypes.Subject);

            if (subClaim != null)
            {
                var principal = Principal.Create("tokenvalidator", result.Claims.ToArray());

                if (result.ReferenceTokenId.IsPresent())
                {
                    principal.Identities.First().AddClaim(new Claim(Constants.ClaimTypes.ReferenceTokenId, result.ReferenceTokenId));
                }

                var isActiveCtx = new IsActiveContext(principal, result.Client);
                await _users.IsActiveAsync(isActiveCtx);

                if (isActiveCtx.IsActive == false)
                {
                    Logger.Warn("User marked as not active: " + subClaim.Value);

                    result.IsError = true;
                    result.Error   = Constants.ProtectedResourceErrors.InvalidToken;
                    result.Claims  = null;

                    return(result);
                }
            }

            // make sure client is still active (if client_id claim is present)
            var clientClaim = result.Claims.FirstOrDefault(c => c.Type == Constants.ClaimTypes.ClientId);

            if (clientClaim != null)
            {
                var client = await _clients.FindClientByIdAsync(clientClaim.Value);

                if (client == null || client.Enabled == false)
                {
                    Logger.Warn("Client deleted or disabled: " + clientClaim.Value);

                    result.IsError = true;
                    result.Error   = Constants.ProtectedResourceErrors.InvalidToken;
                    result.Claims  = null;

                    return(result);
                }
            }

            return(result);
        }
示例#13
0
        public async Task <IActionResult> Index()
        {
            List <Client> clients = _dbContext.Clients.AsNoTracking().ToList();

            List <IdentityServer4.Models.Client> auxList = new List <IdentityServer4.Models.Client>();

            foreach (var item in clients)
            {
                var client = await _clientStore.FindClientByIdAsync(item.ClientId);

                auxList.Add(client);
            }

            BaseListViewModel <ClientViewModel> vm = new BaseListViewModel <ClientViewModel>()
            {
                Data = _mapper.Map <List <ClientViewModel> >(auxList)
            };

            return(View(vm));
        }
示例#14
0
        public async Task <IActionResult> Login([FromBody] LoginViewModel viewModel)
        {
            if (viewModel == null)
            {
                return(StatusCode(400));
            }
            if (string.IsNullOrEmpty(viewModel.PassWord) || string.IsNullOrEmpty(viewModel.UserName))
            {
                return(StatusCode(400));
            }

            if (!string.IsNullOrEmpty(viewModel.returnUri))
            {
                AuthorizationRequest authorizationRequest = await _IdentityInteractionServce.GetAuthorizationContextAsync(viewModel.returnUri);

                if (authorizationRequest == null)
                {
                    return(Json(new { state = "401", Message = "参数错误" }));
                }
                if (await _ClientStore.FindClientByIdAsync(authorizationRequest.ClientId) == null)
                {
                    return(Json(new { state = "401", Message = "参数错误" }));
                }
                forum.DAL.Entity.User user = null;
                //try
                //{
                user = _user.GetAccount(viewModel.UserName, MD5Helper.GetMD5(viewModel.PassWord));
                //}
                //catch(ArgumentException )
                //{
                //    return Json(new { state = "401", Message = "账号或密码为空" });
                //}
                //catch(Exception ex)
                //{
                //    return Json(new { state = "500", Message = "出现错误,请重新刷新页面" });
                //}

                if (user != null)
                {
                    Claim[] claims = new Claim[]
                    {
                        new Claim(ClaimTypes.Name, user.Nickname),
                        new Claim(ClaimTypes.OtherPhone, user.Phone),
                        new Claim(ClaimTypes.PrimarySid, user.ID)
                    };

                    await HttpContext.SignInAsync(viewModel.UserName, claims);

                    return(Json(new { state = "302", location = viewModel.returnUri }));
                }
                return(Json(new { state = "401", Message = "账号或密码错误" }));
            }
            return(View());
        }
示例#15
0
    /// <summary>
    /// Finds a client by id
    /// </summary>
    /// <param name="clientId">The client id</param>
    /// <returns>
    /// The client
    /// </returns>
    public async Task <Client> FindClientByIdAsync(string clientId)
    {
        using var activity = Tracing.StoreActivitySource.StartActivity("CachingClientStore.FindClientById");
        activity?.SetTag(Tracing.Properties.ClientId, clientId);

        var client = await _cache.GetOrAddAsync(clientId,
                                                _options.Caching.ClientStoreExpiration,
                                                async() => await _inner.FindClientByIdAsync(clientId));

        return(client);
    }
示例#16
0
        public async Task <IActionResult> Get(string clientId)
        {
            IdentityServer4.Models.Client client = await _clientStore.FindClientByIdAsync(clientId);

            if (client == null)
            {
                return(NotFound());
            }

            return(Ok(client.Properties));
        }
示例#17
0
        public async Task <Client> FindEnabledClientByIdAsync(string clientId)
        {
            var client = await clientStore.FindClientByIdAsync(clientId);

            if (client != null && client.Enabled == true)
            {
                return(client);
            }

            return(null);
        }
        public async Task <IActionResult> Suspend([FromForm] string clientId)
        {
            var client = await _clients.FindClientByIdAsync(clientId);

            client.AllowedScopes.Remove("openactive-openbooking");
            await _events.RaiseAsync(new GrantsRevokedEvent(User.GetSubjectId(), clientId));

            await BookingPartnerTable.UpdateScope(clientId, "openid profile openactive-ordersfeed", true);

            return(Redirect("/booking-partners/seller-admin"));
        }
    /// <summary>
    /// Finds the enabled client by identifier.
    /// </summary>
    /// <param name="store">The store.</param>
    /// <param name="clientId">The client identifier.</param>
    /// <returns></returns>
    public static async Task <Client> FindEnabledClientByIdAsync(this IClientStore store, string clientId)
    {
        var client = await store.FindClientByIdAsync(clientId);

        if (client != null && client.Enabled)
        {
            return(client);
        }

        return(null);
    }
        public async Task <ClientSecretValidationResult> ValidateAsync()
        {
            Logger.Debug("Start client validation");

            var fail = new ClientSecretValidationResult
            {
                IsError = true
            };

            var parsedSecret = await _parser.ParseAsync(_environment.Environment);

            if (parsedSecret == null)
            {
                await RaiseFailureEvent("unknown", "No client id or secret found");

                Logger.Info("No client secret found");
                return(fail);
            }

            // load client
            var client = await _clients.FindClientByIdAsync(parsedSecret.Id);

            if (client == null)
            {
                await RaiseFailureEvent(parsedSecret.Id, "Unknown client");

                Logger.Info("No client with that id found. aborting");
                return(fail);
            }

            var result = await _validator.ValidateAsync(parsedSecret, client.ClientSecrets);

            if (result.Success)
            {
                Logger.Info("Client validation success");

                var success = new ClientSecretValidationResult
                {
                    IsError = false,
                    Client  = client
                };

                await RaiseSuccessEvent(client.ClientId);

                return(success);
            }

            await RaiseFailureEvent(client.ClientId, "Invalid client secret");

            Logger.Info("Client validation failed.");

            return(fail);
        }
示例#21
0
        public async Task <ClientSecretValidationResult> ValidateAsync(HttpContext context)
        {
            _logger.LogTrace("Start client validation");

            var fail = new ClientSecretValidationResult
            {
                IsError = true
            };

            var parsedSecret = await _parser.ParseAsync(context);

            if (parsedSecret == null)
            {
                await RaiseFailureEvent("unknown", "No client id or secret found");

                _logger.LogInformation("No client secret found");
                return(fail);
            }

            // load client
            var client = await _clients.FindClientByIdAsync(parsedSecret.Id);

            if (client == null)
            {
                await RaiseFailureEvent(parsedSecret.Id, "Unknown client");

                _logger.LogInformation("No client with that id found. aborting");
                return(fail);
            }

            var result = await _validator.ValidateAsync(parsedSecret, client.ClientSecrets);

            if (result.Success)
            {
                _logger.LogInformation("Client validation success");

                var success = new ClientSecretValidationResult
                {
                    IsError = false,
                    Client  = client
                };

                await RaiseSuccessEvent(client.ClientId);

                return(success);
            }

            await RaiseFailureEvent(client.ClientId, "Invalid client secret");

            _logger.LogWarning("Client validation failed client {clientId}.", client.ClientId);

            return(fail);
        }
示例#22
0
        public virtual async Task <System.IO.Stream> Login(LoginViewModel model, SignInMessage message)
        {
            var client = await clientStore.FindClientByIdAsync(message.ClientId);

            var name = client != null ? client.ClientName : null;

            //   return await Render(model, "login", name);
            model.ClientName = name;
            var stream = StringToStream(RazorExtensions.RenderCustomView("login", "home", model));

            return(stream);
        }
示例#23
0
        public WsFederationSigninValidatorTests()
        {
            var goodClient = new Client()
            {
                ProtocolType = IdentityServerConstants.ProtocolTypes.WsFederation,
                RedirectUris = new List <string> {
                    "http://wreply"
                }
            };

            _clientStore.FindClientByIdAsync("http://wtrealm").Returns(goodClient);

            var noWsFedClient = new Client()
            {
                RedirectUris = new List <string> {
                    "http://wreply"
                }
            };

            _clientStore.FindClientByIdAsync("http://noWsFedSupport").Returns(noWsFedClient);
        }
        /// <summary>
        /// Gets the client permissions asynchronous.
        /// </summary>
        /// <param name="subject">The subject identifier.</param>
        /// <returns>
        /// A list of client permissions
        /// </returns>
        /// <exception cref="System.ArgumentNullException">subject</exception>
        public virtual async Task <IEnumerable <ClientPermission> > GetClientPermissionsAsync(string subject)
        {
            if (String.IsNullOrWhiteSpace(subject))
            {
                throw new ArgumentNullException("subject");
            }

            var consents = await this.permissionsStore.LoadAllAsync(subject);

            var scopesNeeded = consents.Select(x => x.Scopes).SelectMany(x => x).Distinct();
            var scopes       = await scopeStore.FindScopesAsync(scopesNeeded);

            var list = new List <ClientPermission>();

            foreach (var consent in consents)
            {
                var client = await clientStore.FindClientByIdAsync(consent.ClientId);

                if (client != null)
                {
                    var identityScopes =
                        from s in scopes
                        where s.Type == ScopeType.Identity && consent.Scopes.Contains(s.Name)
                        select new ClientPermissionDescription
                    {
                        DisplayName = s.DisplayName ?? localizationService.GetScopeDisplayName(s.Name),
                        Description = s.Description ?? localizationService.GetScopeDescription(s.Name)
                    };

                    var resourceScopes =
                        from s in scopes
                        where s.Type == ScopeType.Resource && consent.Scopes.Contains(s.Name)
                        select new ClientPermissionDescription
                    {
                        DisplayName = s.DisplayName ?? localizationService.GetScopeDisplayName(s.Name),
                        Description = s.Description ?? localizationService.GetScopeDescription(s.Name)
                    };

                    list.Add(new ClientPermission
                    {
                        ClientId            = client.ClientId,
                        ClientName          = client.ClientName,
                        ClientUrl           = client.ClientUri,
                        ClientLogoUrl       = client.LogoUri,
                        IdentityPermissions = identityScopes,
                        ResourcePermissions = resourceScopes
                    });
                }
            }

            return(list);
        }
示例#25
0
        public void FetchCompleteClient()
        {
            IClientStore store = Fixture.GetService <IClientStore>();

            Client client = CreateClient();

            Client result = store.FindClientByIdAsync(client.ClientId).Result;

            Assert.Null(result);

            Provider.AddClientAsync(client).Wait();

            Dictionary <string, string> argProps = new Dictionary <string, string>()
            {
                { "prop1", "aaa" }, { "prop2", "bbb" }
            };
            List <Secret> argsSecret = new List <Secret>()
            {
                CreateSecret(), CreateSecret()
            };
            List <Claim> argsClaim = new List <Claim>()
            {
                new Claim("claim1", "val1"), new Claim("claim2", "val2")
            };

            result = store.FindClientByIdAsync(client.ClientId).Result;
            Assert.NotNull(result);
            Assert.Equal(new List <Claim>(), result.Claims);

            Provider.SetClientPropsAsync(result, argProps).Wait();
            Provider.SetClientSecretsAsync(result, argsSecret).Wait();
            Provider.SetClientClaimsAsync(result, argsClaim).Wait();

            result = store.FindClientByIdAsync(client.ClientId).Result;
            Assert.NotNull(result);
            Assert.Equal(argsClaim.Select(p => new Tuple <string, string>(p.Type, p.Value)), result.Claims.Select(p => new Tuple <string, string>(p.Type, p.Value)));
            Assert.Equal(argsSecret, result.ClientSecrets);
            Assert.Equal(argProps, result.Properties);
        }
示例#26
0
        public void CanCreateAndUpdateAndDeleteClient()
        {
            IClientStore store = Fixture.GetService <IClientStore>();

            Client client = CreateClient();

            Client result = store.FindClientByIdAsync(client.ClientId).Result;

            Assert.Null(result);

            Provider.AddClientAsync(client).Wait();

            result = store.FindClientByIdAsync(client.ClientId).Result;
            Assert.NotNull(result);
            Assert.Equal(new string[] { "aaa", "bbb" }, result.RedirectUris);
            Assert.Equal("test", result.ClientName);
            Assert.Equal(AccessTokenType.Reference, result.AccessTokenType);

            result.ClientName = "test2";
            result.RedirectUris.Add("ccc");
            result.RedirectUris.Remove("bbb");

            Provider.UpdateClientAsync(result).Wait();

            result = store.FindClientByIdAsync(client.ClientId).Result;
            Assert.NotNull(result);
            Assert.Equal(new string[] { "aaa", "ccc" }, result.RedirectUris);
            Assert.Equal("test2", result.ClientName);

            List <Client> results = Provider.GetAllClientsAsync().Result.ToList();

            Assert.Equal(1, results.Count);
            Assert.Equal(result.ClientId, results.First().ClientId);

            Provider.RemoveClientAsync(result).Wait();
            result = store.FindClientByIdAsync(client.ClientId).Result;

            Assert.Null(result);
        }
示例#27
0
        public async Task OnGetAsync(string id)
        {
            if (String.IsNullOrEmpty(id))
            {
                ModelState.AddModelError("", "Emtpy ID.");
            }
            CurrentClient = await _clientStore.FindClientByIdAsync(id);

            if (CurrentClient == null)
            {
                ModelState.AddModelError("", "Could not find the requested client");
            }
        }
示例#28
0
        public virtual AuthorizationCode Read(BinaryReader reader)
        {
            if (reader == null)
            {
                throw new ArgumentNullException(nameof(reader));
            }

            var code = new AuthorizationCode {
                IsOpenId        = reader.ReadBoolean(),
                RedirectUri     = reader.ReadString(),
                Nonce           = reader.ReadString(),
                WasConsentShown = reader.ReadBoolean(),
                SessionId       = reader.ReadString(),
                CreationTime    = DateTimeOffset.FromUnixTimeMilliseconds(reader.ReadInt64()),
            };

            // get the client
            var clientId = reader.ReadString();

            code.Client = _clientStore.FindClientByIdAsync(clientId).Result;

            // Read the number of identities stored
            // in the serialized payload.
            var count = reader.ReadInt32();

            if (count > 0)
            {
                var identities = new ClaimsIdentity[count];
                for (var index = 0; index != count; ++index)
                {
                    identities[index] = ReadIdentity(reader);
                }

                code.Subject = new ClaimsPrincipal(identities);
            }

            var scopeCount = reader.ReadInt32();

            if (scopeCount > 0)
            {
                var scopeNames = new List <string>(scopeCount);
                for (var index = 0; index != scopeCount; ++index)
                {
                    scopeNames.Add(reader.ReadString());
                }

                code.RequestedScopes = _scopeStore.FindScopesAsync(scopeNames).Result;
            }

            return(code);
        }
 internal static async Task<Token> FromDbFormat(StoredToken token, IClientStore clientStore)
 {
     return new Token
     {
         Audience = token.Audience,
         Client = await clientStore.FindClientByIdAsync(token.Client),
         Type = token.Type,
         CreationTime = token.CreationTime,
         Issuer = token.Issuer,
         Lifetime = token.Lifetime,
         Version = token.Version,
         Claims = (from c in token.Claims select Data.StoredClientClaim.FromDbFormat(c)).ToList()
     };
 }
        public async Task Invalid_GrantType_For_Client()
        {
            var client = await _clients.FindClientByIdAsync("roclient");

            var validator = Factory.CreateTokenRequestValidator();

            var parameters = new NameValueCollection();

            parameters.Add(Constants.TokenRequest.GrantType, Constants.GrantTypes.ClientCredentials);
            parameters.Add(Constants.TokenRequest.Scope, "resource");

            var result = await validator.ValidateRequestAsync(parameters, client);

            result.IsError.Should().BeTrue();
            result.Error.Should().Be(Constants.TokenErrors.UnauthorizedClient);
        }
        public async Task <IActionResult> Login(string returnUrl = "/")
        {
            var context = await _interaction.GetAuthorizationContextAsync(returnUrl);

            if (context != null)
            {
                var client = await _clientStore.FindClientByIdAsync(context.ClientId);

                if (!client.EnableLocalLogin)
                {
                    return(await ExternalLogin("EDevlet", returnUrl));
                }
            }
            if (!_ipAddressValidator.IsIpAddressInternal())
            {
                return(await ExternalLogin("EDevlet", returnUrl));
            }
            return(View(new LoginModel()
            {
                ReturnUrl = System.Net.WebUtility.UrlEncode(returnUrl),
                IsLocalContext = context == null
            }));
        }
        private static async Task<AuthorizationCode> Version1(
            BsonDocument doc, 
            IClientStore clientStore,
            IScopeStore scopeStore)
        {
            var code = new AuthorizationCode();
            code.CreationTime = doc.GetValueOrDefault("creationTime", code.CreationTime);
            code.IsOpenId = doc.GetValueOrDefault("isOpenId", code.IsOpenId);
            code.RedirectUri = doc.GetValueOrDefault("redirectUri", code.RedirectUri);
            code.WasConsentShown = doc.GetValueOrDefault("wasConsentShown", code.WasConsentShown);
            code.Nonce = doc.GetValueOrDefault("nonce", code.Nonce);
            var claimsPrincipal = new ClaimsPrincipal();
            IEnumerable<ClaimsIdentity> identities = doc.GetValueOrDefault("subject", sub =>
            {
                string authenticationType = sub.GetValueOrDefault("authenticationType", (string)null);
                var claims = sub.GetNestedValueOrDefault("claimSet", ClaimSetSerializer.Deserialize, new Claim[] { });
                ClaimsIdentity identity = authenticationType == null
                    ? new ClaimsIdentity(claims)
                    : new ClaimsIdentity(claims, authenticationType);
                return identity;
            }, new ClaimsIdentity[] { });
            claimsPrincipal.AddIdentities(identities);
            code.Subject = claimsPrincipal;

            var clientId = doc["_clientId"].AsString;
            code.Client = await clientStore.FindClientByIdAsync(clientId);
            if (code.Client == null)
            {
                throw new InvalidOperationException("Client not found when deserializing authorization code. Client id: " + clientId); 
            }

            var scopes = doc.GetValueOrDefault(
                "requestedScopes",
                (IEnumerable<string>)new string[] { }).ToArray();
            code.RequestedScopes = await scopeStore.FindScopesAsync(scopes);
            if (scopes.Count() > code.RequestedScopes.Count())
            {
                throw new InvalidOperationException("Scopes not found when deserializing authorization code. Scopes: " + string.Join(", ",scopes.Except(code.RequestedScopes.Select(x=>x.Name)))); 
            }
            return code;
        }