예제 #1
0
        /// <summary>
        /// Trigger challenges for the given user using a service account.
        /// </summary>
        /// <param name="username">username to trigger challenges for</param>
        /// <param name="domain">optional domain which can be mapped to a privacyIDEA realm</param>
        /// <returns>PIResponse object or null on error</returns>
        public PIResponse TriggerChallenges(string username, string domain = null)
        {
            if (!GetAuthToken())
            {
                Error("Unable to trigger challenges without an auth token!");
                return(null);
            }
            var parameters = new Dictionary <string, string>
            {
                { "user", username }
            };

            AddRealmForDomain(domain, parameters);

            string     response = SendRequest("/validate/triggerchallenge", parameters);
            PIResponse ret      = PIResponse.FromJSON(response, this);

            return(ret);
        }
예제 #2
0
        /// <summary>
        /// Authenticate using the /validate/check endpoint with the username and OTP value.
        /// Optionally, a transaction id can be provided if authentication is done using challenge-response.
        /// </summary>
        /// <param name="user">username</param>
        /// <param name="otp">OTP</param>
        /// <param name="transactionid">optional transaction id to refer to a challenge</param>
        /// <param name="domain">optional domain which can be mapped to a privacyIDEA realm</param>
        /// <returns>PIResponse object or null on error</returns>
        public PIResponse ValidateCheck(string user, string otp, string transactionid = null, string domain = null)
        {
            var parameters = new Dictionary <string, string>
            {
                { "user", user },
                { "pass", otp }
            };

            if (transactionid != null)
            {
                parameters.Add("transaction_id", transactionid);
            }

            AddRealmForDomain(domain, parameters);

            string response = SendRequest("/validate/check", parameters, new List <KeyValuePair <string, string> >());

            return(PIResponse.FromJSON(response, this));
        }
예제 #3
0
        /// <summary>
        /// Authenticate at the /validate/check endpoint using a WebAuthn token instead of the usual OTP value.
        /// This requires the WebAuthnSignResponse and the Origin from the browser.
        /// </summary>
        /// <param name="user">username</param>
        /// <param name="transactionid">transaction id of the webauthn challenge</param>
        /// <param name="webAuthnSignResponse">the WebAuthnSignResponse string in json format as returned from the browser</param>
        /// <param name="origin">origin also returned by the browser</param>
        /// <param name="domain">optional domain which can be mapped to a privacyIDEA realm</param>
        /// <returns>PIResponse object or null on error</returns>
        public PIResponse ValidateCheckWebAuthn(string user, string transactionid, string webAuthnSignResponse, string origin, string domain = null)
        {
            if (string.IsNullOrEmpty(user) || string.IsNullOrEmpty(transactionid) || string.IsNullOrEmpty(webAuthnSignResponse) || string.IsNullOrEmpty(origin))
            {
                Log("ValidateCheckWebAuthn called with missing parameter: user="******", transactionid=" + transactionid
                    + ", WebAuthnSignResponse=" + webAuthnSignResponse + ", origin=" + origin);
                return(null);
            }

            // Parse the WebAuthnSignResponse and add mandatory parameters
            JToken root;

            try
            {
                root = JToken.Parse(webAuthnSignResponse);
            }
            catch (JsonReaderException jex)
            {
                Error("WebAuthnSignRequest does not have the required format! " + jex.Message);
                return(null);
            }

            string credentialid      = (string)root["credentialid"];
            string clientdata        = (string)root["clientdata"];
            string signaturedata     = (string)root["signaturedata"];
            string authenticatordata = (string)root["authenticatordata"];

            var parameters = new Dictionary <string, string>
            {
                { "user", user },
                { "pass", "" },
                { "transaction_id", transactionid },
                { "credentialid", credentialid },
                { "clientdata", clientdata },
                { "signaturedata", signaturedata },
                { "authenticatordata", authenticatordata }
            };

            // Optionally add UserHandle and AssertionClientExtensions
            string userhandle = (string)root["userhandle"];

            if (!string.IsNullOrEmpty(userhandle))
            {
                parameters.Add("userhandle", userhandle);
            }

            string ace = (string)root["assertionclientextensions"];

            if (!string.IsNullOrEmpty(ace))
            {
                parameters.Add("assertionclientextensions", ace);
            }

            AddRealmForDomain(domain, parameters);

            // The origin has to be set in the header for WebAuthn authentication
            var headers = new List <KeyValuePair <string, string> >
            {
                new KeyValuePair <string, string>("Origin", origin)
            };

            string response = SendRequest("/validate/check", parameters, headers);

            return(PIResponse.FromJSON(response, this));
        }
예제 #4
0
        public static PIResponse FromJSON(string json, PrivacyIDEA privacyIDEA)
        {
            if (string.IsNullOrEmpty(json))
            {
                if (privacyIDEA != null)
                {
                    privacyIDEA.Error("Json to parse is empty!");
                }
                return(null);
            }

            PIResponse ret = new PIResponse();

            ret.Raw = json;
            try
            {
                JObject jobj   = JObject.Parse(json);
                JToken  result = jobj["result"];
                if (result != null)
                {
                    ret.Status = (bool)result["status"];

                    JToken jVal = result["value"];
                    if (jVal != null)
                    {
                        ret.Value = (bool)jVal;
                    }

                    JToken error = result["error"];
                    if (error != null)
                    {
                        ret.ErrorCode    = (int)error["code"];
                        ret.ErrorMessage = (string)error["message"];
                    }
                }

                JToken detail = jobj["detail"];
                if (detail != null && detail.Type != JTokenType.Null)
                {
                    ret.TransactionID = (string)detail["transaction_id"];
                    ret.Message       = (string)detail["message"];
                    ret.Type          = (string)detail["type"];
                    ret.Serial        = (string)detail["serial"];

                    JArray multiChallenge = detail["multi_challenge"] as JArray;
                    if (multiChallenge != null)
                    {
                        foreach (JToken element in multiChallenge.Children())
                        {
                            string message       = (string)element["message"];
                            string transactionid = (string)element["transaction_id"];
                            string type          = (string)element["type"];
                            string serial        = (string)element["serial"];
                            if (type == "webauthn")
                            {
                                PIWebAuthnSignRequest tmp = new PIWebAuthnSignRequest();
                                JToken attr = element["attributes"];
                                tmp.WebAuthnSignRequest = attr["webAuthnSignRequest"].ToString(Formatting.None);
                                tmp.WebAuthnSignRequest.Replace("\n", "");
                                tmp.Message       = message;
                                tmp.Serial        = serial;
                                tmp.TransactionID = transactionid;
                                tmp.Type          = type;
                                ret.Challenges.Add(tmp);
                            }
                            else
                            {
                                PIChallenge tmp = new PIChallenge();
                                tmp.Message       = message;
                                tmp.Serial        = serial;
                                tmp.TransactionID = transactionid;
                                tmp.Type          = type;
                                ret.Challenges.Add(tmp);
                            }
                        }
                    }
                }
            }
            catch (JsonException je)
            {
                if (privacyIDEA != null)
                {
                    privacyIDEA.Error(je);
                }
                return(null);
            }

            return(ret);
        }