Esempio n. 1
0
 /// <summary>
 /// Token request for refresh
 /// </summary>
 public OAuthTokenRequest(TokenClaimsPrincipal current, String scope)
 {
     this.GrantType    = "refresh_token";
     this.RefreshToken = current.RefreshToken;
     this.Scope        = scope;
 }
Esempio n. 2
0
        /// <summary>
        /// Authenticate the user
        /// </summary>
        /// <param name="principal">Principal.</param>
        /// <param name="password">Password.</param>
        public System.Security.Principal.IPrincipal Authenticate(System.Security.Principal.IPrincipal principal, string password, String tfaSecret)
        {
            AuthenticatingEventArgs e = new AuthenticatingEventArgs(principal.Identity.Name, password)
            {
                Principal = principal
            };

            this.Authenticating?.Invoke(this, e);
            if (e.Cancel)
            {
                this.m_tracer.TraceWarning("Pre-Event ordered cancel of auth {0}", principal);
                return(e.Principal);
            }

            var localIdp = new LocalIdentityService();

            // Get the scope being requested
            String scope = "*";

            if (principal is ClaimsPrincipal)
            {
                scope = (principal as ClaimsPrincipal).Claims.FirstOrDefault(o => o.Type == ClaimTypes.OpenIzScopeClaim)?.Value ?? scope;
            }
            else if (principal is SQLitePrincipal && password == null)
            {
                return(localIdp.Authenticate(principal, password));
            }
            else
            {
                scope = ApplicationContext.Current.GetRestClient("imsi")?.Description.Endpoint[0].Address ??
                        ApplicationContext.Current.GetRestClient("ami")?.Description.Endpoint[0].Address ??
                        "*";
            }

            // Authenticate
            IPrincipal retVal = null;

            try
            {
                using (IRestClient restClient = ApplicationContext.Current.GetRestClient("acs"))
                {
                    try
                    {
                        // Set credentials
                        restClient.Credentials = new OAuthTokenServiceCredentials(principal);

                        // Create grant information
                        OAuthTokenRequest request = null;
                        if (!String.IsNullOrEmpty(password))
                        {
                            request = new OAuthTokenRequest(principal.Identity.Name, password, scope);
                        }
                        else if (principal is TokenClaimsPrincipal)
                        {
                            request = new OAuthTokenRequest(principal as TokenClaimsPrincipal, scope);
                        }
                        else
                        {
                            request = new OAuthTokenRequest(principal.Identity.Name, null, scope);
                        }

                        try
                        {
                            restClient.Requesting += (o, p) =>
                            {
                                p.AdditionalHeaders.Add("X-OpenIZClient-Claim", Convert.ToBase64String(Encoding.UTF8.GetBytes(String.Format("{0}={1}", ClaimTypes.OpenIzScopeClaim, scope))));
                                if (!String.IsNullOrEmpty(tfaSecret))
                                {
                                    p.AdditionalHeaders.Add("X-OpenIZ-TfaSecret", tfaSecret);
                                }
                            };

                            // Invoke
                            if (ApplicationContext.Current.GetService <INetworkInformationService>().IsNetworkAvailable)
                            {
                                if (principal.Identity.Name == ApplicationContext.Current.Configuration.GetSection <SecurityConfigurationSection>().DeviceName)
                                {
                                    restClient.Description.Endpoint[0].Timeout = restClient.Description.Endpoint[0].Timeout * 2;
                                }
                                else
                                {
                                    restClient.Description.Endpoint[0].Timeout = (int)(restClient.Description.Endpoint[0].Timeout * 0.6666f);
                                }

                                OAuthTokenResponse response = restClient.Post <OAuthTokenRequest, OAuthTokenResponse>("oauth2_token", "application/x-www-urlform-encoded", request);
                                retVal = new TokenClaimsPrincipal(response.AccessToken, response.TokenType, response.RefreshToken);
                            }
                            else
                            {
                                this.m_tracer.TraceWarning("Network unavailable, trying local");
                                try
                                {
                                    retVal = localIdp.Authenticate(principal, password);
                                }
                                catch (Exception ex2)
                                {
                                    this.m_tracer.TraceError("Error falling back to local IDP: {0}", ex2);
                                    throw new SecurityException(String.Format(Strings.err_offline_use_cache_creds, ex2.Message), ex2);
                                }
                            }
                            this.Authenticated?.Invoke(this, new AuthenticatedEventArgs(principal.Identity.Name, password, true)
                            {
                                Principal = retVal
                            });
                        }
                        catch (WebException ex) // Raw level web exception
                        {
                            // Not network related, but a protocol level error
                            if (ex.Status == WebExceptionStatus.ProtocolError)
                            {
                                throw;
                            }

                            this.m_tracer.TraceWarning("Original OAuth2 request failed trying local. {0}", ex.Message);
                            try
                            {
                                retVal = localIdp.Authenticate(principal, password);
                            }
                            catch (Exception ex2)
                            {
                                this.m_tracer.TraceError("Error falling back to local IDP: {0}", ex2);
                                throw new SecurityException(String.Format(Strings.err_offline_use_cache_creds, ex2.Message), ex2);
                            }
                        }
                        catch (SecurityException ex)
                        {
                            this.m_tracer.TraceError("Server was contacted however the token is invalid: {0}", ex.Message);
                            throw;
                        }
                        catch (Exception ex) // fallback to local
                        {
                            try
                            {
                                this.m_tracer.TraceWarning("Original OAuth2 request failed trying local. {0}", ex.Message);
                                retVal = localIdp.Authenticate(principal, password);
                            }
                            catch (Exception ex2)
                            {
                                this.m_tracer.TraceError("Error falling back to local IDP: {0}", ex2);

                                throw new SecurityException(String.Format(Strings.err_offline_use_cache_creds, ex2.Message), ex2);
                            }
                        }


                        // We have a match! Lets make sure we cache this data
                        // TODO: Clean this up
                        try
                        {
                            if (!(retVal is SQLitePrincipal))
                            {
                                ApplicationContext.Current.GetService <IThreadPoolService>().QueueUserWorkItem(o => this.SynchronizeSecurity(password, o as IPrincipal), retVal);
                            }
                        }
                        catch (Exception ex)
                        {
                            try
                            {
                                this.m_tracer.TraceWarning("Failed to fetch remote security parameters - {0}", ex.Message);
                                retVal = localIdp.Authenticate(principal, password);
                            }
                            catch (Exception ex2)
                            {
                                this.m_tracer.TraceError("Error falling back to local IDP: {0}", ex2);
                                throw new SecurityException(String.Format(Strings.err_offline_use_cache_creds, ex2.Message));
                            }
                        }
                    }
                    catch (RestClientException <OAuthTokenResponse> ex)
                    {
                        this.m_tracer.TraceError("REST client exception: {0}", ex.Message);
                        var se = new SecurityException(
                            String.Format("err_oauth2_{0}", ex.Result.Error),
                            ex
                            );
                        se.Data.Add("detail", ex.Result);
                        throw se;
                    }
                    catch (SecurityTokenException ex)
                    {
                        this.m_tracer.TraceError("TOKEN exception: {0}", ex.Message);
                        throw new SecurityException(
                                  String.Format("err_token_{0}", ex.Type),
                                  ex
                                  );
                    }
                    catch (SecurityException ex)
                    {
                        this.m_tracer.TraceError("Security exception: {0}", ex.Message);
                        throw;
                    }
                    catch (Exception ex)
                    {
                        this.m_tracer.TraceError("Generic exception: {0}", ex);
                        throw new SecurityException(
                                  Strings.err_authentication_exception,
                                  ex);
                    }
                }
            }
            catch
            {
                this.Authenticated?.Invoke(this, new AuthenticatedEventArgs(principal.Identity.Name, password, false)
                {
                    Principal = retVal
                });
                throw;
            }

            return(retVal);
        }