예제 #1
0
        public async Task <bool> AuthenticateAsync(string id, Option <string> modelId, Option <string> authChain)
        {
            try
            {
                // See if we received direct credentials for the target identity
                bool hasToken = this.clientTokens.TryGetValue(id, out ClientToken clientToken);

                // Otherwise, this could be a child Edge acting OnBehalfOf of the target,
                // in which case we would have the actor's credentials instead
                if (!hasToken)
                {
                    Option <string> actorDeviceId = AuthChainHelpers.GetActorDeviceId(authChain);
                    hasToken = actorDeviceId.Map(actor => this.clientTokens.TryGetValue($"{actor}/{CoreConstants.EdgeHubModuleId}", out clientToken)).GetOrElse(false);
                }

                if (hasToken)
                {
                    // Lock the auth-state check and the auth call to avoid
                    // redundant calls into the authenticator
                    using (await this.identitySyncLock.LockAsync())
                    {
                        if (this.authenticatedClients.ContainsKey(id))
                        {
                            // We've previously authenticated this client already
                            return(true);
                        }
                        else
                        {
                            IClientCredentials clientCredentials = this.clientCredentialsFactory.GetWithSasToken(
                                clientToken.DeviceId,
                                clientToken.ModuleId.OrDefault(),
                                string.Empty,
                                clientToken.Token,
                                true,
                                modelId,
                                authChain);

                            if (await this.authenticator.AuthenticateAsync(clientCredentials))
                            {
                                // Authentication success, add an entry for the authenticated
                                // client identity, the value in the dictionary doesn't matter
                                // as we're effectively using it as a thread-safe HashSet
                                this.authenticatedClients[id] = default(byte);

                                // No need to add the new credentials to the cache, as the
                                // authenticator already implicitly handles it
                                return(true);
                            }
                        }
                    }
                }

                return(false);
            }
            catch (Exception e)
            {
                Events.ErrorAuthenticatingIdentity(id, e);
                return(false);
            }
        }
예제 #2
0
        public async Task <IDeviceIdentity> GetAsync(string clientId, string username, string password, EndPoint clientAddress)
        {
            try
            {
                Preconditions.CheckNonWhiteSpace(username, nameof(username));
                Preconditions.CheckNonWhiteSpace(clientId, nameof(clientId));

                ClientInfo clientInfo = this.usernameParser.Parse(username);
                clientInfo.ModelId.ForEach(async m => await this.metadataStore.SetModelId(clientInfo.DeviceId, m));
                IClientCredentials          deviceCredentials = null;
                Option <IClientCredentials> actorCredentials  = Option.None <IClientCredentials>();

                if (!string.IsNullOrEmpty(password))
                {
                    deviceCredentials = this.clientCredentialsFactory.GetWithSasToken(clientInfo.DeviceId, clientInfo.ModuleId, clientInfo.DeviceClientType, password, false, clientInfo.ModelId, clientInfo.AuthChain);

                    // For OnBehalfOf connections, we'll get the token for the actor EdgeHub instead
                    // of the actual leaf/module, so we need to construct the credentials accordingly
                    Option <string> actorDeviceIdOption = AuthChainHelpers.GetActorDeviceId(clientInfo.AuthChain);
                    actorCredentials = actorDeviceIdOption.Map(actorDeviceId =>
                                                               this.clientCredentialsFactory.GetWithSasToken(
                                                                   actorDeviceId,
                                                                   Microsoft.Azure.Devices.Edge.Hub.Core.Constants.EdgeHubModuleId,
                                                                   clientInfo.DeviceClientType,
                                                                   password,
                                                                   false,
                                                                   clientInfo.ModelId,
                                                                   clientInfo.AuthChain));
                }
                else if (this.remoteCertificate.HasValue)
                {
                    if (!this.clientCertAuthAllowed)
                    {
                        Events.CertAuthNotEnabled(clientInfo.DeviceId, clientInfo.ModuleId);
                        return(UnauthenticatedDeviceIdentity.Instance);
                    }

                    this.remoteCertificate.ForEach(
                        cert =>
                    {
                        deviceCredentials = this.clientCredentialsFactory.GetWithX509Cert(
                            clientInfo.DeviceId,
                            clientInfo.ModuleId,
                            clientInfo.DeviceClientType,
                            cert,
                            this.remoteCertificateChain,
                            clientInfo.ModelId,
                            Option.None <string>());
                    });
                }
                else
                {
                    Events.AuthNotFound(clientInfo.DeviceId, clientInfo.ModuleId);
                    return(UnauthenticatedDeviceIdentity.Instance);
                }

                if (deviceCredentials == null ||
                    !clientId.Equals(deviceCredentials.Identity.Id, StringComparison.Ordinal) ||
                    !await this.authenticator.AuthenticateAsync(actorCredentials.GetOrElse(deviceCredentials)))
                {
                    Events.Error(clientId, username);
                    return(UnauthenticatedDeviceIdentity.Instance);
                }

                await this.metadataStore.SetMetadata(deviceCredentials.Identity.Id, clientInfo.DeviceClientType, clientInfo.ModelId);

                Events.Success(clientId, username);
                return(new ProtocolGatewayIdentity(deviceCredentials, clientInfo.ModelId));
            }
            catch (Exception ex)
            {
                Events.ErrorCreatingIdentity(ex);
                throw;
            }
        }