Esempio n. 1
0
        protected JsonDocument DecodeToken()
        {
            if (_decodedToken != null)
            {
                return(_decodedToken);
            }

            if (AccessToken == null)
            {
                throw new InvalidOperationException($"{nameof(AccessToken)} not found.");
            }

            var parts = AccessToken.Split('.');

            if (parts.Length != 3)
            {
                throw new InvalidOperationException($"{nameof(AccessToken)} must have 3 parts");
            }

            var decodedBytes = CoreHelpers.Base64UrlDecode(parts[1]);

            if (decodedBytes == null || decodedBytes.Length < 1)
            {
                throw new InvalidOperationException($"{nameof(AccessToken)} must have 3 parts");
            }

            _decodedToken = JsonDocument.Parse(decodedBytes);
            return(_decodedToken);
        }
Esempio n. 2
0
        public JObject DecodeToken()
        {
            if (_decodedAccessToken != null)
            {
                return(_decodedAccessToken);
            }
            if (_accessTokenForDecoding == null)
            {
                throw new InvalidOperationException("Access token not found.");
            }
            var parts = _accessTokenForDecoding.Split('.');

            if (parts.Length != 3)
            {
                throw new InvalidOperationException("JWT must have 3 parts.");
            }
            var decodedBytes = CoreHelpers.Base64UrlDecode(parts[1]);

            if (decodedBytes == null || decodedBytes.Length < 1)
            {
                throw new InvalidOperationException("Cannot decode the token.");
            }
            _decodedAccessToken = JObject.Parse(Encoding.UTF8.GetString(decodedBytes));
            return(_decodedAccessToken);
        }
Esempio n. 3
0
        public async Task <IActionResult> Access(string id, [FromBody] SendAccessRequestModel model)
        {
            var guid = new Guid(CoreHelpers.Base64UrlDecode(id));

            var(send, passwordRequired, passwordInvalid) =
                await _sendService.AccessAsync(guid, model.Password);

            if (passwordRequired)
            {
                return(new UnauthorizedResult());
            }
            if (passwordInvalid)
            {
                await Task.Delay(2000);

                throw new BadRequestException("Invalid password.");
            }
            if (send == null)
            {
                throw new NotFoundException();
            }

            var sendResponse = new SendAccessResponseModel(send, _globalSettings);

            if (send.UserId.HasValue)
            {
                var creator = await _userService.GetUserByIdAsync(send.UserId.Value);

                sendResponse.CreatorIdentifier = creator.Email;
            }
            return(new ObjectResult(sendResponse));
        }
        public async Task <IActionResult> GetSendFileDownloadData(string encodedSendId,
                                                                  string fileId, [FromBody] SendAccessRequestModel model)
        {
            var sendId = new Guid(CoreHelpers.Base64UrlDecode(encodedSendId));
            var send   = await _sendRepository.GetByIdAsync(sendId);

            if (send == null)
            {
                throw new BadRequestException("Could not locate send");
            }

            var(url, passwordRequired, passwordInvalid) = await _sendService.GetSendFileDownloadUrlAsync(send, fileId,
                                                                                                         model.Password);

            if (passwordRequired)
            {
                return(new UnauthorizedResult());
            }
            if (passwordInvalid)
            {
                await Task.Delay(2000);

                throw new BadRequestException("Invalid password.");
            }
            if (send == null)
            {
                throw new NotFoundException();
            }

            return(new ObjectResult(new SendFileDownloadDataResponseModel()
            {
                Id = fileId,
                Url = url,
            }));
        }
        private static readonly string _tag_log = "Fido2Builder"; // Tag for the logs in the Fido2Builder

        /// <summary>
        /// Build the request for Sign In using FIDO2
        /// </summary>
        public static PublicKeyCredentialRequestOptions ParsePublicKeyCredentialRequestOptions(Dictionary <string, object> data)
        {
            PublicKeyCredentialRequestOptions.Builder builder = new PublicKeyCredentialRequestOptions.Builder();
            foreach (KeyValuePair <string, object> entry in data)
            {
                switch (entry.Key)
                {
                case "challenge":     // Challenge to be sign
                    builder.SetChallenge(CoreHelpers.Base64UrlDecode((string)entry.Value));
                    break;

                case "allowCredentials":     // List of FIDO2 Keys that already are registered to the user and should only use one of this FIDO2 Keys
                    builder.SetAllowList(ParseCredentialDescriptors((List <Dictionary <string, object> >)entry.Value));
                    break;

                case "rpId":     // Server ID information
                    builder.SetRpId((string)entry.Value);
                    break;

                case "timeout":     // temp limit to sign in
                    builder.SetTimeoutSeconds((Java.Lang.Double)(double) entry.Value);
                    break;

                case "userVerification":     // Require that user has to verify before using FIDO2
                    //Skip
                    break;

                case "extensions":     // Adicional parameter to improve even more the security
                    //Skip
                    break;
                }
            }
            return(builder.Build());
        }
Esempio n. 6
0
        /// <summary>
        /// Build the part of request where contains the user information, exemple name and id
        /// </summary>
        public static PublicKeyCredentialUserEntity ParseUser(Fido2User data)
        {
            if (data == null)
            {
                return(null);
            }

            string id          = null;
            string name        = null;
            string icon        = null;
            string displayName = null;

            if (data.Id != null && data.Id.Length > 0)
            {
                // id of user
                id = data.Id;
            }
            if (data.Name != null && data.Name.Length > 0)
            {
                // name of user
                name = data.Name;
            }
            if (data.Icon != null && data.Icon.Length > 0)
            {
                // icon of user
                icon = data.Icon;
            }
            if (data.DisplayName != null && data.DisplayName.Length > 0)
            {
                // name of user to display to the user
                displayName = data.DisplayName;
            }

            return(new PublicKeyCredentialUserEntity(CoreHelpers.Base64UrlDecode(id), name, icon, displayName));
        }
        /// <summary>
        /// Build the part of request where contains the user information, exemple name and id
        /// </summary>
        public static PublicKeyCredentialUserEntity ParseUser(Dictionary <string, string> data)
        {
            string id          = null;
            string name        = null;
            string icon        = null;
            string displayName = null;

            foreach (KeyValuePair <string, string> entry in data)
            {
                switch (entry.Key)
                {
                case "id":     // id of user
                    id = entry.Value;
                    break;

                case "name":     // name of user
                    name = entry.Value;
                    break;

                case "icon":     // icon of user
                    icon = entry.Value;
                    break;

                case "displayName":     // name of user to display to the user
                    displayName = entry.Value;
                    break;
                }
            }
            return(new PublicKeyCredentialUserEntity(CoreHelpers.Base64UrlDecode(id), name, icon, displayName));
        }
Esempio n. 8
0
        /// <summary>
        /// Build the request for Regist a New FIDO2 Key using FIDO2
        /// </summary>
        public static PublicKeyCredentialCreationOptions ParsePublicKeyCredentialCreationOptions(Fido2RegistrationChallengeResponse data)
        {
            if (data == null)
            {
                return(null);
            }

            PublicKeyCredentialCreationOptions.Builder builder = new PublicKeyCredentialCreationOptions.Builder();
            if (data.Challenge != null && data.Challenge.Length > 0)
            {
                // Challenge to be sign
                builder.SetChallenge(CoreHelpers.Base64UrlDecode(data.Challenge));
            }
            if (data.ExcludeCredentials != null && data.ExcludeCredentials.Count > 0)
            {
                // List of FIDO2 Keys that already are registered to the user and shouldn't be excluded of registering again
                builder.SetExcludeList(ParseCredentialDescriptors(data.ExcludeCredentials));
            }
            if (data.Timeout > 0)
            {
                // temp limit to regist a new key
                builder.SetTimeoutSeconds((Java.Lang.Double)data.Timeout);
            }
            if (data.User != null)
            {
                // User information
                builder.SetUser(ParseUser(data.User));
            }
            if (data.Rp != null)
            {
                // Server information
                builder.SetRp(ParseRp(data.Rp));
            }
            if (data.PubKeyCredParams != null)
            {
                //Algorithm information
                builder.SetParameters(ParseParameters(data.PubKeyCredParams));
            }
            if (data.AuthenticatorSelection != null)
            {
                // Options of regist selected
                builder.SetAuthenticatorSelection(ParseSelection(data.AuthenticatorSelection));
            }
            if (data.attestation != null)
            {
                // It is how the signature is given, anonymously or direct.
                //Skip
            }
            if (data.Extensions != null)
            {
                // Adicional parameter to improve even more the security
                //Skip
            }
            return(builder.Build());
        }
        /// <summary>
        /// Build the request for Regist a New FIDO2 Key using FIDO2
        /// </summary>
        public static PublicKeyCredentialCreationOptions ParsePublicKeyCredentialCreationOptions(Dictionary <string, object> data)
        {
            PublicKeyCredentialCreationOptions.Builder builder = new PublicKeyCredentialCreationOptions.Builder();
            foreach (KeyValuePair <string, object> entry in data)
            {
                switch (entry.Key)
                {
                case "user":     // User information
                    builder.SetUser(ParseUser((Dictionary <string, string>)entry.Value));
                    break;

                case "challenge":     // Challenge to be sign
                    builder.SetChallenge(CoreHelpers.Base64UrlDecode((string)entry.Value));
                    break;

                case "pubKeyCredParams":     //Algorithm information
                    builder.SetParameters(ParseParameters((List <Dictionary <string, object> >)entry.Value));
                    break;

                case "authenticatorSelection":     // Options of regist selected
                    builder.SetAuthenticatorSelection(ParseSelection((Dictionary <string, string>)entry.Value));
                    break;

                case "excludeCredentials":     // List of FIDO2 Keys that already are registered to the user and shouldn't be excluded of registering again
                    builder.SetExcludeList(ParseCredentialDescriptors((List <Dictionary <string, object> >)entry.Value));
                    break;

                case "rpId":     // Server ID information
                    builder.SetRp(new PublicKeyCredentialRpEntity((string)entry.Value, null, null));
                    break;

                case "rp":     // Server information
                    builder.SetRp(ParseRp((Dictionary <string, string>)entry.Value));
                    break;

                case "timeout":     // temp limit to regist a new key
                    builder.SetTimeoutSeconds((Java.Lang.Double)(double) entry.Value);
                    break;

                case "userVerification":     // Require that user has to verify before using FIDO2
                    //Skip
                    break;

                case "attestation":     //It is how the signature is given, anonymously or direct.
                    //Skip
                    break;
                }
            }
            return(builder.Build());
        }
Esempio n. 10
0
        /// <summary>
        /// Build the part of request where contains the FIDO2 Key information
        /// </summary>
        public static List <PublicKeyCredentialDescriptor> ParseCredentialDescriptors(List <Fido2CredentialDescriptor> listData)
        {
            if (listData == null && listData.Count > 0)
            {
                return(new List <PublicKeyCredentialDescriptor>());
            }

            List <PublicKeyCredentialDescriptor> credentials = new List <PublicKeyCredentialDescriptor>();

            string           id         = null;
            string           type       = null;
            List <Transport> transports = null;

            foreach (Fido2CredentialDescriptor data in listData)
            {
                id         = null;
                type       = null;
                transports = new List <Transport>();

                if (data.Id != null && data.Id.Length > 0)
                {
                    // id of the FIDO2 key
                    id = data.Id;
                }
                if (data.Type != null && data.Type.Length > 0)
                {
                    // type of the FIDO2 key
                    type = data.Type;
                }
                if (data.Transports != null && data.Transports.Count > 0)
                {
                    // list of types of transport accepted (NFC, USB, INTERNAL, BLUETOOTH) of the FIDO2 key
                    foreach (string transport in (List <string>)data.Transports)
                    {
                        transports.Add(Transport.FromString(transport));
                    }
                }

                credentials.Add(new PublicKeyCredentialDescriptor(type, CoreHelpers.Base64UrlDecode(id), transports));
            }

            return(credentials);
        }
Esempio n. 11
0
        public async Task <IActionResult> GetSendFileDownloadData(string encodedSendId,
                                                                  string fileId, [FromBody] SendAccessRequestModel model)
        {
            // Uncomment whenever we want to require the `send-id` header
            //if (!_currentContext.HttpContext.Request.Headers.ContainsKey("Send-Id") ||
            //    _currentContext.HttpContext.Request.Headers["Send-Id"] != encodedSendId)
            //{
            //    throw new BadRequestException("Invalid Send-Id header.");
            //}

            var sendId = new Guid(CoreHelpers.Base64UrlDecode(encodedSendId));
            var send   = await _sendRepository.GetByIdAsync(sendId);

            if (send == null)
            {
                throw new BadRequestException("Could not locate send");
            }

            var(url, passwordRequired, passwordInvalid) = await _sendService.GetSendFileDownloadUrlAsync(send, fileId,
                                                                                                         model.Password);

            if (passwordRequired)
            {
                return(new UnauthorizedResult());
            }
            if (passwordInvalid)
            {
                await Task.Delay(2000);

                throw new BadRequestException("Invalid password.");
            }
            if (send == null)
            {
                throw new NotFoundException();
            }

            return(new ObjectResult(new SendFileDownloadDataResponseModel()
            {
                Id = fileId,
                Url = url,
            }));
        }
Esempio n. 12
0
        private static readonly string _tag_log = "Fido2Builder"; // Tag for the logs in the Fido2Builder

        /// <summary>
        /// Build the request for Sign In using FIDO2
        /// </summary>
        public static PublicKeyCredentialRequestOptions ParsePublicKeyCredentialRequestOptions(Fido2AuthenticationChallengeResponse data)
        {
            if (data == null)
            {
                return(null);
            }

            PublicKeyCredentialRequestOptions.Builder builder = new PublicKeyCredentialRequestOptions.Builder();

            if (data.Challenge != null && data.Challenge.Length > 0)
            {
                // Challenge to be sign
                builder.SetChallenge(CoreHelpers.Base64UrlDecode(data.Challenge));
            }
            if (data.AllowCredentials != null && data.AllowCredentials.Count > 0)
            {
                // List of FIDO2 Keys that already are registered to the user and should only use one of this FIDO2 Keys
                builder.SetAllowList(ParseCredentialDescriptors(data.AllowCredentials));
            }
            if (data.RpId != null && data.RpId.Length > 0)
            {
                // Server ID information
                builder.SetRpId(data.RpId);
            }
            if (data.Timeout > 0)
            {
                // temp limit to sign in
                builder.SetTimeoutSeconds((Java.Lang.Double)data.Timeout);
            }
            if (data.UserVerification != null)
            {
                // Require that user has to verify before using FIDO2
                //Skip
            }
            if (data.Extensions != null)
            {
                // Adicional parameter to improve even more the security
                //Skip
            }
            return(builder.Build());
        }
Esempio n. 13
0
        public async Task <IActionResult> Access(string id, [FromBody] SendAccessRequestModel model)
        {
            // Uncomment whenever we want to require the `send-id` header
            //if (!_currentContext.HttpContext.Request.Headers.ContainsKey("Send-Id") ||
            //    _currentContext.HttpContext.Request.Headers["Send-Id"] != id)
            //{
            //    throw new BadRequestException("Invalid Send-Id header.");
            //}

            var guid = new Guid(CoreHelpers.Base64UrlDecode(id));

            var(send, passwordRequired, passwordInvalid) =
                await _sendService.AccessAsync(guid, model.Password);

            if (passwordRequired)
            {
                return(new UnauthorizedResult());
            }
            if (passwordInvalid)
            {
                await Task.Delay(2000);

                throw new BadRequestException("Invalid password.");
            }
            if (send == null)
            {
                throw new NotFoundException();
            }

            var sendResponse = new SendAccessResponseModel(send, _globalSettings);

            if (send.UserId.HasValue && !send.HideEmail.GetValueOrDefault())
            {
                var creator = await _userService.GetUserByIdAsync(send.UserId.Value);

                sendResponse.CreatorIdentifier = creator.Email;
            }
            return(new ObjectResult(sendResponse));
        }
Esempio n. 14
0
        public async Task <IActionResult> Access(string id, [FromBody] SendAccessRequestModel model)
        {
            var guid = new Guid(CoreHelpers.Base64UrlDecode(id));

            var(send, passwordRequired, passwordInvalid) =
                await _sendService.AccessAsync(guid, model.Password);

            if (passwordRequired)
            {
                return(new UnauthorizedResult());
            }
            if (passwordInvalid)
            {
                await Task.Delay(2000);

                throw new BadRequestException("Invalid password.");
            }
            if (send == null)
            {
                throw new NotFoundException();
            }

            return(new ObjectResult(new SendAccessResponseModel(send, _globalSettings)));
        }
        /// <summary>
        /// Build the part of request where contains the FIDO2 Key information
        /// </summary>
        public static List <PublicKeyCredentialDescriptor> ParseCredentialDescriptors(List <Dictionary <string, object> > listData)
        {
            List <PublicKeyCredentialDescriptor> credentials = new List <PublicKeyCredentialDescriptor>();
            string           id         = null;
            string           type       = null;
            List <Transport> transports = null;

            foreach (Dictionary <string, object> data in listData)
            {
                id         = null;
                type       = null;
                transports = new List <Transport>();
                foreach (KeyValuePair <string, object> entry in data)
                {
                    switch (entry.Key)
                    {
                    case "id":     // id of the FIDO2 key
                        id = (string)entry.Value;
                        break;

                    case "type":     // type of the FIDO2 key
                        type = (string)entry.Value;
                        break;

                    case "transports":     // list of types of transport accepted (NFC, USB, INTERNAL, BLUETOOTH) of the FIDO2 key
                        foreach (string transport in (List <string>)entry.Value)
                        {
                            transports.Add(Transport.FromString(transport));
                        }
                        break;
                    }
                }
                credentials.Add(new PublicKeyCredentialDescriptor(type, CoreHelpers.Base64UrlDecode(id), transports));
            }
            return(credentials);
        }
Esempio n. 16
0
        public IEnumerable <ValidationResult> Validate(ValidationContext context)
        {
            var i18nService = context.GetService(typeof(II18nService)) as I18nService;

            if (ConfigType == SsoType.OpenIdConnect)
            {
                if (string.IsNullOrWhiteSpace(Authority))
                {
                    yield return(new ValidationResult(i18nService.GetLocalizedHtmlString("AuthorityValidationError"),
                                                      new[] { nameof(Authority) }));
                }

                if (string.IsNullOrWhiteSpace(ClientId))
                {
                    yield return(new ValidationResult(i18nService.GetLocalizedHtmlString("ClientIdValidationError"),
                                                      new[] { nameof(ClientId) }));
                }

                if (string.IsNullOrWhiteSpace(ClientSecret))
                {
                    yield return(new ValidationResult(i18nService.GetLocalizedHtmlString("ClientSecretValidationError"),
                                                      new[] { nameof(ClientSecret) }));
                }
            }
            else if (ConfigType == SsoType.Saml2)
            {
                if (string.IsNullOrWhiteSpace(IdpEntityId))
                {
                    yield return(new ValidationResult(i18nService.GetLocalizedHtmlString("IdpEntityIdValidationError"),
                                                      new[] { nameof(IdpEntityId) }));
                }

                if (IdpBindingType == Saml2BindingType.Artifact && string.IsNullOrWhiteSpace(IdpArtifactResolutionServiceUrl))
                {
                    yield return(new ValidationResult(i18nService.GetLocalizedHtmlString("Saml2BindingTypeValidationError"),
                                                      new[] { nameof(IdpArtifactResolutionServiceUrl) }));
                }

                if (!Uri.IsWellFormedUriString(IdpEntityId, UriKind.Absolute) && string.IsNullOrWhiteSpace(IdpSingleSignOnServiceUrl))
                {
                    yield return(new ValidationResult(i18nService.GetLocalizedHtmlString("IdpSingleSignOnServiceUrlValidationError"),
                                                      new[] { nameof(IdpSingleSignOnServiceUrl) }));
                }

                if (InvalidServiceUrl(IdpSingleSignOnServiceUrl))
                {
                    yield return(new ValidationResult(i18nService.GetLocalizedHtmlString("IdpSingleSignOnServiceUrlInvalid"),
                                                      new[] { nameof(IdpSingleSignOnServiceUrl) }));
                }

                if (InvalidServiceUrl(IdpArtifactResolutionServiceUrl))
                {
                    yield return(new ValidationResult(i18nService.GetLocalizedHtmlString("IdpArtifactResolutionServiceUrlInvalid"),
                                                      new[] { nameof(IdpArtifactResolutionServiceUrl) }));
                }

                if (InvalidServiceUrl(IdpSingleLogoutServiceUrl))
                {
                    yield return(new ValidationResult(i18nService.GetLocalizedHtmlString("IdpSingleLogoutServiceUrlInvalid"),
                                                      new[] { nameof(IdpSingleLogoutServiceUrl) }));
                }

                if (!string.IsNullOrWhiteSpace(IdpX509PublicCert))
                {
                    // Validate the certificate is in a valid format
                    ValidationResult failedResult = null;
                    try
                    {
                        var certData = CoreHelpers.Base64UrlDecode(StripPemCertificateElements(IdpX509PublicCert));
                        new X509Certificate2(certData);
                    }
                    catch (FormatException)
                    {
                        failedResult = new ValidationResult(i18nService.GetLocalizedHtmlString("IdpX509PublicCertInvalidFormatValidationError"),
                                                            new[] { nameof(IdpX509PublicCert) });
                    }
                    catch (CryptographicException cryptoEx)
                    {
                        failedResult = new ValidationResult(i18nService.GetLocalizedHtmlString("IdpX509PublicCertCryptographicExceptionValidationError", cryptoEx.Message),
                                                            new[] { nameof(IdpX509PublicCert) });
                    }
                    catch (Exception ex)
                    {
                        failedResult = new ValidationResult(i18nService.GetLocalizedHtmlString("IdpX509PublicCertValidationError", ex.Message),
                                                            new[] { nameof(IdpX509PublicCert) });
                    }
                    if (failedResult != null)
                    {
                        yield return(failedResult);
                    }
                }
            }
        }