Bad credentials ошибка

Здравствуйте, при создании собственной формы входа возникла проблема: при попытке залогиниться появляется ошибка с сообщением bad credentials (хотя если логиниться через форму — все проходит)

web.xml

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>    

<security:http pattern="/admin/**" use-expressions="true" name="securityFilterChain" create-session="stateless">
          <security:http-basic/>
          <security:intercept-url pattern="/**" access="hasRole('ADMIN')" />

   </security:http>

   <security:http use-expressions="true">
          <security:intercept-url pattern="/login" access="permitAll()"/>
          <security:intercept-url pattern="/**" access="isAuthenticated()"/>
          <security:form-login login-page="/login"
                  default-target-url="/restaurants"
                  authentication-failure-url="/login?error=true"
                  login-processing-url="/spring_security_check"/>
          <security:logout logout-success-url="/login"/>
   </security:http>

   <security:authentication-manager>
          <security:authentication-provider>
                 <security:user-service>
                        <security:user name="anatoly@mail.ru" password="pastol" authorities="ADMIN"/>
                 </security:user-service>
                 <!--<security:jdbc-user-service data-source-ref="dataSource"
                                             users-by-username-query="SELECT email, password FROM users WHERE email = ?"
                                             authorities-by-username-query="SELECT u.email, r.role FROM users u, roles r WHERE u.id=r.userid AND u.email = ?"/>-->
                 </security:authentication-provider>
   </security:authentication-manager>

Форма входа

  <form:form class="navbar-form navbar-right" role="form" action="spring_security_check" method="post">
    <div class="form-group">
      <input type="text" placeholder="Email" class="form-control" name='username'>
    </div>
    <div class="form-group">
      <input type="password" placeholder="Password" class="form-control" name='password'>
    </div>
    <button type="submit" class="btn btn-success">Войти</button>
  </form:form>

zRrr's user avatar

zRrr

5,2473 золотых знака19 серебряных знаков35 бронзовых знаков

задан 18 мая 2016 в 16:41

Анатолий Михайлин's user avatar

Вы не указали имена полей в форме ввода.

<security:form-login login-page="/login"
              default-target-url="/restaurants"
              authentication-failure-url="/login?error=true"
              username-parameter="username"
              password-parameter="password" />

Во-вторых, зачем login-processing-url? При задании этого параметра необходим метод с этим урлом, который будет этот запрос обрабатывать. Зачем? Можно же воспользоваться стандартным. Собственно, ошибка именно потому, что нет этого урла.

<c:url var="loginUrl" value="/login" />
<form action="${loginUrl}" method="post">

В-третьих, если у вас Spring Security 4, обратите внимание на этот мой ответ.

Удачи!

Дух сообщества's user avatar

ответ дан 18 мая 2016 в 16:54

naiad09's user avatar

naiad09naiad09

4212 серебряных знака12 бронзовых знаков

@lyschoening It is not ambiguous, that is the purpose of the specification. Consider this scenario:

Given that users with the admin role can create articles
And Mary is an admin user with a valid authentication token
And Mary makes a POST request to /articles
And with the authentication token in the Authorization header
And with a valid JSON formatted request body
The API will return a 200 response code

Then consider this scenario:

Given that users with the editor role cannot create articles
And Bob is an editor and not an admin with a valid authentication token
And Bob makes a POST request to /articles
And with the authentication token in the Authorization header
And with a valid JSON formatted request body
The API will return a 403 response code

In the both scenarios «the server understood the request» because it contained valid parameters and a valid authentication token. However, in the second scenario the server «refuses to authorize it» because the user identified by the token does not have sufficient privileges to create articles.

Also, wouldn’t it be conceivable that someone simply might not wish to give out JWTs to a certain user despite their credentials being correct?

What use would this be unless you’re providing a public, unauthenticated API?

Invalid credentials aren’t necessarily a client error

It depends on the requirements of the request. It is the client’s responsibility to provide an interface to collect the username/password pair to be passed in the body of a request to the authorization endpoint. This endpoint does not require the Authorization header to be supplied in order to get a 200 response. 401 and 403 response codes are tailored to indicate an issue with the presence or value of the Authorization header. Consider this scenario:

Given a user named Janet without an authentication token
And Janet makes a POST request to /articles
And without the Authorization header
And with a valid JSON formatted request body
The API will return a 401 response code

If this scenario happened within the context of your client application, the client would then display an interface to collect the user’s username/password and make a request to the authorization endpoint:

Given a user named Janet without an authentication token
And Janet makes a POST request to /authorize
And with a valid JSON formatted request body containing her username and password
The API will return a 200 response code
And the body will contain a valid authentication token

Now the client application Janet is using can take that token and retry the previous scenario and it would result in a 200 is she had sufficient access privileges or a 403 if she did not.

Assume your Web API is protected and a client attempts to access it without the appropriate credentials. How do you deal with this scenario? Most likely, you know you have to return an HTTP status code. But what is the more appropriate one? Should it be 401 Unauthorized or 403 Forbidden? Or maybe something else?

As usual, it depends 🙂. It depends on the specific scenario and also on the security level you want to provide. Let’s go a little deeper.

If you prefer, you can watch a video on the same topic:

Web APIs and HTTP Status Codes

Before going into the specific topic, let’s take a quick look at the rationale of HTTP status codes in general. Most Web APIs are inspired by the REST paradigm. Although the vast majority of them don’t actually implement REST, they usually follow a few RESTful conventions when it comes to HTTP status codes.

The basic principle behind these conventions is that a status code returned in a response must make the client aware of what is going on and what the server expects the client to do next. You can fulfill this principle by giving answers to the following questions:

  • Is there a problem or not?
  • If there is a problem, on which side is it? On the client or on the server side?
  • If there is a problem, what should the client do?

This is a general principle that applies to all the HTTP status codes. For example, if the client receives a 200 OK status code, it knows there was no problem with its request and expects the requested resource representation in the response’s body. If the client receives a 201 Created status code, it knows there was no problem with its request, but the resource representation is not in the response’s body. Similarly, when the client receives a 500 Internal Server Error status code, it knows that this is a problem on the server side, and the client can’t do anything to mitigate it.

In summary, your Web API’s response should provide the client with enough information to realize how it can move forward opportunely.

Let’s consider the case when a client attempts to call a protected API. If the client provides the appropriate credentials (e.g., a valid access token), its request is accepted and processed. What happens when the client has no appropriate credentials? What status code should your API return when a request is not legitimate? What information should it return, and how to guarantee the best security experience?

Fortunately, in the OAuth security context, you have some guidelines. Of course, you can use them even if you don’t use OAuth to secure your API.

«The basic principle behind REST status code conventions is that a status code must make the client aware of what is going on and what the server expects the client to do next»

Tweet

Tweet This

When to Use 400 Bad Request?

Let’s start with a simple case: a client calls your protected API, omitting a required parameter. In this case, your API should respond with a 400 Bad Request status code. In fact, if that parameter is required, your API can’t even process the client request. The client’s request is malformed.

Your API should return the same status code even when the client provides an unsupported parameter or repeats the same parameter multiple times in its request. In both cases, the client’s request is not as expected and should be refused.

Following the general principle discussed above, the client should be empowered to understand what to do to fix the problem. So, you should add in your response’s body what was wrong with the client’s request. You can provide those details in the format you prefer, such as simple text, XML, JSON, etc. However, using a standard format like the one proposed by the Problem Details for HTTP APIs specifications would be more appropriate to enable uniform problem management across clients.

For example, if your client calls your API with an empty value for the required data parameter, the API could reply with the following response:

HTTP/1.1 400 Bad Request
Content-Type: application/problem+json
Content-Language: en

{
  "type": "https://myapi.com/validation-error",
  "title": "Validation error",
  "detail": "Your request parameters are not valid.",
  "invalid-params": [
    {
      "name": "data",
      "reason": "cannot be blank."
    }
  ]
}

When to Use 401 Unauthorized?

Now, let’s assume that the client calls your protected API with a well-formed request but no valid credentials. For example, in the OAuth context, this may fall in one of the following cases:

  • An access token is missing.
  • An access token is expired, revoked, malformed, or invalid for other reasons.

In both cases, the appropriate status code to reply with is 401 Unauthorized. In the spirit of mutual collaboration between the client and the API, the response must include a hint on how to obtain such authorization. That comes in the form of the WWW-Authenticate header with the specific authentication scheme to use. For example, in the case of OAuth2, the response should look like the following:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="example"

You have to use the Bearer scheme and provide the realm parameter to indicate the set of resources the API is protecting.

If the client request does not include any access token, demonstrating that it wasn’t aware that the API is protected, the API’s response should not include any other information.

On the other hand, if the client’s request includes an expired access token, the API response could include the reason for the denied access, as shown in the following example:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="example",
                  error="invalid_token",
                  error_description="The access token expired"

When to Use 403 Forbidden?

Let’s explore a different case now. Assume, for example, that your client sends a request to modify a document and provides a valid access token to the API. However, that token doesn’t include or imply any permission or scope that allows the client to perform the desired action.

In this case, your API should respond with a 403 Forbidden status code. With this status code, your API tells the client that the credentials it provided (e.g., the access token) are valid, but it needs appropriate privileges to perform the requested action.

To help the client understand what to do next, your API may include what privileges are needed in its response. For example, according to the OAuth2 guidelines, your API may include information about the missing scope to access the protected resource.

Try out the most powerful authentication platform for free.Get started →

Security Considerations

When you plan how to respond to your client’s requests, always keep security in mind.

How to deal with response details

A primary security concern is to avoid providing useful information to potential attackers. In other words, returning detailed information in the API responses to attempts to access protected resources may be a security risk.

For example, suppose your API returns a 401 Unauthorized status code with an error description like The access token is expired. In this case, it gives information about the token itself to a potential attacker. The same happens when your API responds with a 403 Forbidden status code and reports the missing scope or privilege.

In other words, sharing this information can improve the collaboration between the client and the server, according to the basic principle of the REST paradigm. However, the same information may be used by malicious attackers to elaborate their attack strategy.

Since this additional information is optional for both the HTTP specifications and the OAuth2 bearer token guidelines, maybe you should think carefully about sharing it. The basic principle on sharing that additional information should be based on the answer to this question: how would the client behave any differently if provided with more information?

For example, in the case of a response with a 401 Unauthorized status code, does the client’s behavior change when it knows that its token is expired or revoked? In any case, it must request a new token. So, adding that information doesn’t change the client’s behavior.

Different is the case with 403 Forbidden. By informing your client that it needs a specific permission, your API makes it learn what to do next, i.e., requesting that additional permission. If your API doesn’t provide this additional information, it will behave differently because it doesn’t know what to do to access that resource.

Don’t let the client know…

Now, assume your client attempts to access a resource that it MUST NOT access at all, for example, because it belongs to another user. What status code should your API return? Should it return a 403 or a 401 status code?

You may be tempted to return a 403 status code anyway. But, actually, you can’t suggest any missing permission because that client has no way to access that resource. So, the 403 status code gives no actual helpful information. You may think that returning a 401 status code makes sense in this case. After all, the resource belongs to another user, so the request should come from a different user.

However, since that resource shouldn’t be reached by the current client, the best option is to hide it. Letting the client (and especially the user behind it) know that resource exists could possibly lead to Insecure Direct Object References (IDOR), an access control vulnerability based on the knowledge of resources you shouldn’t access. Therefore, in these cases, your API should respond with a 404 Not Found status code. This is an option provided by the HTTP specification:

An origin server that wishes to «hide» the current existence of a forbidden target resource MAY instead respond with a status code of 404 (Not Found).

For example, this is the strategy adopted by GitHub when you don’t have any permission to access a repository. This approach avoids that an attacker attempts to access the resource again with a slightly different strategy.

How to deal with bad requests

When a client sends a malformed request, you know you should reply with a 400 Bad Request status code. You may be tempted to analyze the request’s correctness before evaluating the client credentials. You shouldn’t do this for a few reasons:

  • By evaluating the client credentials before the request’s validity, you avoid your API processing requests that aren’t allowed to be there.
  • A potential attacker could figure out how a request should look without being authenticated, even before obtaining or stealing a legitimate access token.

Also, consider that in infrastructures with an API gateway, the client credentials will be evaluated beforehand by the gateway itself, which doesn’t know at all what parameters the API is expecting.

The security measures discussed here must be applied in the production environment. Of course, in the development environment, your API can provide all the information you need to be able to diagnose the causes of an authorization failure.

Recap

Throughout this article, you learned that:

  • 400 Bad Request is the status code to return when the form of the client request is not as the API expects.
  • 401 Unauthorized is the status code to return when the client provides no credentials or invalid credentials.
  • 403 Forbidden is the status code to return when a client has valid credentials but not enough privileges to perform an action on a resource.

You also learned that some security concerns might arise when your API exposes details that malicious attackers may exploit. In these cases, you may adopt a more restricted strategy by including just the needed details in the response body or even using the 404 Not Found status code instead of 403 Forbidden or 401 Unauthorized.

The following cheat sheet summarizes what you learned:

4xx HTTP status codes cheat sheet

Sorry that you’re having trouble. Since you’ve deleted the token from your GitHub account, if you still want to use some hub commands, you will have to re-authenticate.

You can either delete your ~/.config/hub file, or edit the file to delete the oauth_token line containing your old token. Then, run a hub command that previously didn’t work. You should be asked for your GitHub account credentials now. Note that this will create a new personal access token for hub in your account.

This error message will be better handled after #225 ships. Ideally, hub will detect that your credentials are invalid and offer you to re-authenticate without you having to edit tokens yourself.

I have found a lot of answers and explanations for the meanings of HTTP status codes. My question is specifically about the POST request to a login endpoint, which asks for username and password for example and the scenario where incorrect ones are provided.

Some thoughts:

400 Bad Response
I think this code is not appropriate, because it says the request was syntactically incorrect and not understood by the server, which is not the case here. The login data is just semantically not correct.

401 Unauthorized
Here is the tricky part for me.
If 401 can only occur on requests requiring an authentication header then this is not correct. But if 401 can occur on all requests, which require authentication (either as header or in the body) then 401 is a candidate.

403 Forbidden
Usually, 403 is returned if the user already is authenticated and known to the system but requested a resource he/she is not allowed to access.
The user definitely is not authenticated before the login. I don’t know if there is a semantic for 403 for unauthenticated users.

I’m happy to be told the answer or hear your thoughts.

@lyschoening It is not ambiguous, that is the purpose of the specification. Consider this scenario:

Given that users with the admin role can create articles
And Mary is an admin user with a valid authentication token
And Mary makes a POST request to /articles
And with the authentication token in the Authorization header
And with a valid JSON formatted request body
The API will return a 200 response code

Then consider this scenario:

Given that users with the editor role cannot create articles
And Bob is an editor and not an admin with a valid authentication token
And Bob makes a POST request to /articles
And with the authentication token in the Authorization header
And with a valid JSON formatted request body
The API will return a 403 response code

In the both scenarios «the server understood the request» because it contained valid parameters and a valid authentication token. However, in the second scenario the server «refuses to authorize it» because the user identified by the token does not have sufficient privileges to create articles.

Also, wouldn’t it be conceivable that someone simply might not wish to give out JWTs to a certain user despite their credentials being correct?

What use would this be unless you’re providing a public, unauthenticated API?

Invalid credentials aren’t necessarily a client error

It depends on the requirements of the request. It is the client’s responsibility to provide an interface to collect the username/password pair to be passed in the body of a request to the authorization endpoint. This endpoint does not require the Authorization header to be supplied in order to get a 200 response. 401 and 403 response codes are tailored to indicate an issue with the presence or value of the Authorization header. Consider this scenario:

Given a user named Janet without an authentication token
And Janet makes a POST request to /articles
And without the Authorization header
And with a valid JSON formatted request body
The API will return a 401 response code

If this scenario happened within the context of your client application, the client would then display an interface to collect the user’s username/password and make a request to the authorization endpoint:

Given a user named Janet without an authentication token
And Janet makes a POST request to /authorize
And with a valid JSON formatted request body containing her username and password
The API will return a 200 response code
And the body will contain a valid authentication token

Now the client application Janet is using can take that token and retry the previous scenario and it would result in a 200 is she had sufficient access privileges or a 403 if she did not.

Assume your Web API is protected and a client attempts to access it without the appropriate credentials. How do you deal with this scenario? Most likely, you know you have to return an HTTP status code. But what is the more appropriate one? Should it be 401 Unauthorized or 403 Forbidden? Or maybe something else?

As usual, it depends 🙂. It depends on the specific scenario and also on the security level you want to provide. Let’s go a little deeper.

If you prefer, you can watch a video on the same topic:

Web APIs and HTTP Status Codes

Before going into the specific topic, let’s take a quick look at the rationale of HTTP status codes in general. Most Web APIs are inspired by the REST paradigm. Although the vast majority of them don’t actually implement REST, they usually follow a few RESTful conventions when it comes to HTTP status codes.

The basic principle behind these conventions is that a status code returned in a response must make the client aware of what is going on and what the server expects the client to do next. You can fulfill this principle by giving answers to the following questions:

  • Is there a problem or not?
  • If there is a problem, on which side is it? On the client or on the server side?
  • If there is a problem, what should the client do?

This is a general principle that applies to all the HTTP status codes. For example, if the client receives a 200 OK status code, it knows there was no problem with its request and expects the requested resource representation in the response’s body. If the client receives a 201 Created status code, it knows there was no problem with its request, but the resource representation is not in the response’s body. Similarly, when the client receives a 500 Internal Server Error status code, it knows that this is a problem on the server side, and the client can’t do anything to mitigate it.

In summary, your Web API’s response should provide the client with enough information to realize how it can move forward opportunely.

Let’s consider the case when a client attempts to call a protected API. If the client provides the appropriate credentials (e.g., a valid access token), its request is accepted and processed. What happens when the client has no appropriate credentials? What status code should your API return when a request is not legitimate? What information should it return, and how to guarantee the best security experience?

Fortunately, in the OAuth security context, you have some guidelines. Of course, you can use them even if you don’t use OAuth to secure your API.

«The basic principle behind REST status code conventions is that a status code must make the client aware of what is going on and what the server expects the client to do next»

Tweet

Tweet This

When to Use 400 Bad Request?

Let’s start with a simple case: a client calls your protected API, omitting a required parameter. In this case, your API should respond with a 400 Bad Request status code. In fact, if that parameter is required, your API can’t even process the client request. The client’s request is malformed.

Your API should return the same status code even when the client provides an unsupported parameter or repeats the same parameter multiple times in its request. In both cases, the client’s request is not as expected and should be refused.

Following the general principle discussed above, the client should be empowered to understand what to do to fix the problem. So, you should add in your response’s body what was wrong with the client’s request. You can provide those details in the format you prefer, such as simple text, XML, JSON, etc. However, using a standard format like the one proposed by the Problem Details for HTTP APIs specifications would be more appropriate to enable uniform problem management across clients.

For example, if your client calls your API with an empty value for the required data parameter, the API could reply with the following response:

HTTP/1.1 400 Bad Request
Content-Type: application/problem+json
Content-Language: en

{
  "type": "https://myapi.com/validation-error",
  "title": "Validation error",
  "detail": "Your request parameters are not valid.",
  "invalid-params": [
    {
      "name": "data",
      "reason": "cannot be blank."
    }
  ]
}

When to Use 401 Unauthorized?

Now, let’s assume that the client calls your protected API with a well-formed request but no valid credentials. For example, in the OAuth context, this may fall in one of the following cases:

  • An access token is missing.
  • An access token is expired, revoked, malformed, or invalid for other reasons.

In both cases, the appropriate status code to reply with is 401 Unauthorized. In the spirit of mutual collaboration between the client and the API, the response must include a hint on how to obtain such authorization. That comes in the form of the WWW-Authenticate header with the specific authentication scheme to use. For example, in the case of OAuth2, the response should look like the following:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="example"

You have to use the Bearer scheme and provide the realm parameter to indicate the set of resources the API is protecting.

If the client request does not include any access token, demonstrating that it wasn’t aware that the API is protected, the API’s response should not include any other information.

On the other hand, if the client’s request includes an expired access token, the API response could include the reason for the denied access, as shown in the following example:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="example",
                  error="invalid_token",
                  error_description="The access token expired"

When to Use 403 Forbidden?

Let’s explore a different case now. Assume, for example, that your client sends a request to modify a document and provides a valid access token to the API. However, that token doesn’t include or imply any permission or scope that allows the client to perform the desired action.

In this case, your API should respond with a 403 Forbidden status code. With this status code, your API tells the client that the credentials it provided (e.g., the access token) are valid, but it needs appropriate privileges to perform the requested action.

To help the client understand what to do next, your API may include what privileges are needed in its response. For example, according to the OAuth2 guidelines, your API may include information about the missing scope to access the protected resource.

Try out the most powerful authentication platform for free.Get started →

Security Considerations

When you plan how to respond to your client’s requests, always keep security in mind.

How to deal with response details

A primary security concern is to avoid providing useful information to potential attackers. In other words, returning detailed information in the API responses to attempts to access protected resources may be a security risk.

For example, suppose your API returns a 401 Unauthorized status code with an error description like The access token is expired. In this case, it gives information about the token itself to a potential attacker. The same happens when your API responds with a 403 Forbidden status code and reports the missing scope or privilege.

In other words, sharing this information can improve the collaboration between the client and the server, according to the basic principle of the REST paradigm. However, the same information may be used by malicious attackers to elaborate their attack strategy.

Since this additional information is optional for both the HTTP specifications and the OAuth2 bearer token guidelines, maybe you should think carefully about sharing it. The basic principle on sharing that additional information should be based on the answer to this question: how would the client behave any differently if provided with more information?

For example, in the case of a response with a 401 Unauthorized status code, does the client’s behavior change when it knows that its token is expired or revoked? In any case, it must request a new token. So, adding that information doesn’t change the client’s behavior.

Different is the case with 403 Forbidden. By informing your client that it needs a specific permission, your API makes it learn what to do next, i.e., requesting that additional permission. If your API doesn’t provide this additional information, it will behave differently because it doesn’t know what to do to access that resource.

Don’t let the client know…

Now, assume your client attempts to access a resource that it MUST NOT access at all, for example, because it belongs to another user. What status code should your API return? Should it return a 403 or a 401 status code?

You may be tempted to return a 403 status code anyway. But, actually, you can’t suggest any missing permission because that client has no way to access that resource. So, the 403 status code gives no actual helpful information. You may think that returning a 401 status code makes sense in this case. After all, the resource belongs to another user, so the request should come from a different user.

However, since that resource shouldn’t be reached by the current client, the best option is to hide it. Letting the client (and especially the user behind it) know that resource exists could possibly lead to Insecure Direct Object References (IDOR), an access control vulnerability based on the knowledge of resources you shouldn’t access. Therefore, in these cases, your API should respond with a 404 Not Found status code. This is an option provided by the HTTP specification:

An origin server that wishes to «hide» the current existence of a forbidden target resource MAY instead respond with a status code of 404 (Not Found).

For example, this is the strategy adopted by GitHub when you don’t have any permission to access a repository. This approach avoids that an attacker attempts to access the resource again with a slightly different strategy.

How to deal with bad requests

When a client sends a malformed request, you know you should reply with a 400 Bad Request status code. You may be tempted to analyze the request’s correctness before evaluating the client credentials. You shouldn’t do this for a few reasons:

  • By evaluating the client credentials before the request’s validity, you avoid your API processing requests that aren’t allowed to be there.
  • A potential attacker could figure out how a request should look without being authenticated, even before obtaining or stealing a legitimate access token.

Also, consider that in infrastructures with an API gateway, the client credentials will be evaluated beforehand by the gateway itself, which doesn’t know at all what parameters the API is expecting.

The security measures discussed here must be applied in the production environment. Of course, in the development environment, your API can provide all the information you need to be able to diagnose the causes of an authorization failure.

Recap

Throughout this article, you learned that:

  • 400 Bad Request is the status code to return when the form of the client request is not as the API expects.
  • 401 Unauthorized is the status code to return when the client provides no credentials or invalid credentials.
  • 403 Forbidden is the status code to return when a client has valid credentials but not enough privileges to perform an action on a resource.

You also learned that some security concerns might arise when your API exposes details that malicious attackers may exploit. In these cases, you may adopt a more restricted strategy by including just the needed details in the response body or even using the 404 Not Found status code instead of 403 Forbidden or 401 Unauthorized.

The following cheat sheet summarizes what you learned:

4xx HTTP status codes cheat sheet

@lyschoening It is not ambiguous, that is the purpose of the specification. Consider this scenario:

Given that users with the admin role can create articles
And Mary is an admin user with a valid authentication token
And Mary makes a POST request to /articles
And with the authentication token in the Authorization header
And with a valid JSON formatted request body
The API will return a 200 response code

Then consider this scenario:

Given that users with the editor role cannot create articles
And Bob is an editor and not an admin with a valid authentication token
And Bob makes a POST request to /articles
And with the authentication token in the Authorization header
And with a valid JSON formatted request body
The API will return a 403 response code

In the both scenarios «the server understood the request» because it contained valid parameters and a valid authentication token. However, in the second scenario the server «refuses to authorize it» because the user identified by the token does not have sufficient privileges to create articles.

Also, wouldn’t it be conceivable that someone simply might not wish to give out JWTs to a certain user despite their credentials being correct?

What use would this be unless you’re providing a public, unauthenticated API?

Invalid credentials aren’t necessarily a client error

It depends on the requirements of the request. It is the client’s responsibility to provide an interface to collect the username/password pair to be passed in the body of a request to the authorization endpoint. This endpoint does not require the Authorization header to be supplied in order to get a 200 response. 401 and 403 response codes are tailored to indicate an issue with the presence or value of the Authorization header. Consider this scenario:

Given a user named Janet without an authentication token
And Janet makes a POST request to /articles
And without the Authorization header
And with a valid JSON formatted request body
The API will return a 401 response code

If this scenario happened within the context of your client application, the client would then display an interface to collect the user’s username/password and make a request to the authorization endpoint:

Given a user named Janet without an authentication token
And Janet makes a POST request to /authorize
And with a valid JSON formatted request body containing her username and password
The API will return a 200 response code
And the body will contain a valid authentication token

Now the client application Janet is using can take that token and retry the previous scenario and it would result in a 200 is she had sufficient access privileges or a 403 if she did not.

You might see the following error message appear when attempting an Artifactory login:

HTTP Status 500 – Bad credentials
type Exception report
message Bad credentials
description The server encountered an internal error that prevented it from fulfilling this request.
exception
org.springframework.security.authentication.BadCredentialsException: Bad credentials

org.springframework.security.authentication.dao.DaoAuthenticationProvider.additionalAuthenticationChecks(DaoAuthenticationProvider.java:87)

org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:149)

org.artifactory.security.db.DbAuthenticationProvider.authenticate(DbAuthenticationProvider.java:47)

org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:156)

org.artifactory.security.RealmAwareAuthenticationManager.authenticate(RealmAwareAuthenticationManager.java:72)

This is probably being triggered as a result of a database corruption of the anonymous user, which is used during login to Artifactory. If that file has been altered from its default settings, you’ll receive a failure message like the one above.

The easiest way to resolve this problem is to go into the database, delete the anonymous user and, thereafter, restart Artifactory. This will force Artifactory to automatically recreate the anonymous user and, thereby, allow you to log in. If this doesn’t resolve the problem, make sure that your database password credentials stored in etc/storage.properties can be used to log into the database that you’re using.

In my previous post, you learned how to troubleshoot HTTP Error 503. Today, we will look into how to troubleshoot 401 – Unauthorized: Access is denied due to invalid credentials in Internet Information Services (IIS).

Contents

  1. 401 – Unauthorized
  2. How IIS authentication works
  3. Cause of error
  4. Debugging the error
  5. Resolving the error
  6. Common 401 substatus codes
  7. Conclusion
  • Author
  • Recent Posts

Surender Kumar has more than twelve years of experience in server and network administration. His fields of interest are Windows Servers, Active Directory, PowerShell, web servers, networking, Linux, virtualization, and penetration testing. He loves writing for his blog.

401 – Unauthorized

401 Unauthorized Access is denied due to invalid credentials

401 Unauthorized Access is denied due to invalid credentials

The 401 – Unauthorized: Access is denied due to invalid credentials error is a common access-related error that you may experience with a website hosted on IIS.

How IIS authentication works

The error itself indicates that it is caused by a failure to authorize access. Someone who is a beginner in IIS could find the error description «you do not have permission to view this directory or page using the credentials that you supplied» slightly confusing. If you think from an end user’s perspective, you might be wondering when you supplied any credentials while accessing the website. Well, this happened automatically on the server side. By default, every website hosted on IIS has anonymous authentication enabled.

If you open the IIS Manager, select your website, and then double-click Authentication under the IIS section in the Features view, you will see the various authentication modes (such as basic authentication, forms authentication, anonymous authentication, etc.) that are supported by IIS.

Viewing various authentication modes supported by a website in IIS

Viewing various authentication modes supported by a website in IIS

Each website has to have at least one authentication mode enabled and, by default, Anonymous Authentication mode enabled. Authentication is a mechanism that is used to verify the visitor’s identity to your website. See the following screenshot for reference:

Default authentication modes supported by a website in IIS

Default authentication modes supported by a website in IIS

Anonymous authentication allows visitors to access the public content of your website anonymously without having to supply any credentials. If you don’t want to use it, select the authentication mode, and then click Disable in the Actions pane on the right. To view or modify which credentials are used by anonymous authentication, click the Edit link on the right. You will see two options, as shown in the following screenshot:

View or modify the credentials used by anonymous authentication in IIS

View or modify the credentials used by anonymous authentication in IIS

By default, each website is set to use the IUSR user for anonymous user identity, which is a built-in account starting with IIS version 7. If you are using a custom username as the application pool identity, make sure you select the application pool identity option here. This way, you don’t have to worry about updating the user’s password in the website configuration over and over when the user’s password is changed.

Cause of error

The primary cause of the 401 – Unauthorized: Access is denied due to invalid credentials error is that you are using a custom username as the application pool identity. In simple terms, when you set the application pool to use a custom application pool identity (a custom username and password) rather than the default identity (which is ApplicationPoolIdentity), the Anonymous Authentication mode of the website continues using the IUSR user for authentication, which results in this error.

Debugging the error

As discussed in previous posts, the error page we saw above is a custom error page and does not reveal much helpful information for administrators. If you enable the detailed errors, you will see an error page with much detailed information, as shown in the following screenshot:

Error message 401.3 – You do not have permission to view this directory or page using the credentials you supplied (acc

Error message 401.3 – You do not have permission to view this directory or page using the credentials you supplied (access denied due to Access Control Lists)

The detailed error gave you the HTTP 401.3 status code, which will guide you in checking the access control permissions on the file system. Make sure that the user who is set as the application pool identity has the read and execute permissions on the website’s root directory. If the error persists, the most likely cause is incorrect anonymous user identity. The following screenshot shows the problematic scenario:

Mismatched application pool identity and anonymous authentication identity user in IIS

Mismatched application pool identity and anonymous authentication identity user in IIS

The screenshot shows a mismatched application pool identity and anonymous authentication identity on the website, which is causing the error. For a website to work properly, both should be the same.

Resolving the error

Now that you know the cause of the HTTP 401.3 status code, do the following to fix the error:

If you are using a custom username as the application pool identity, make sure that the user has read and execute permissions on the website’s root directory.

Ensuring that the custom application pool user has read and execute permissions on the root directory

Ensuring that the custom application pool user has read and execute permissions on the root directory

If you’re using the default ApplicationPoolIdentity for your application pool, make sure that the built-in IUSR user or IIS_IUSRS group has exactly the same permissions as shown in the screenshot below.

Ensuring that the default application pool identity has read and execute permissions on the root directory

Ensuring that the default application pool identity has read and execute permissions on the root directory

If the error persists, edit the Anonymous Authentication setting of your website, as explained in the How IIS authentication works section. Be sure it is set to use the Application pool identity. See the following screenshot for reference:

Modifying the anonymous authentication identity to match the application pool identity in IIS

Modifying the anonymous authentication identity to match the application pool identity in IIS

Common 401 substatus codes

The following table covers the most common HTTP 401 substatus codes, along with their possible causes and troubleshooting advice:

Subscribe to 4sysops newsletter!

Status Code Possible Cause Troubleshooting Advice
401.1 Logon failed The logon attempt failed, probably due to an invalid user name or password.
401.2 Logon failed due to server configuration The 401.2 status code indicates that there is a problem in the authentication configuration on the server.
401.3 Unauthorized due to ACL on resource We covered how to fix this error above.

Conclusion

I hope you’re enjoying this series of resolving common HTTP errors. In the next post, we will discuss how to fix the HTTP Error 403.14 – Forbidden error.

When we fail to log in, we may write the wrong username or the wrong password, but for security reasons, the server usually does not explicitly indicate whether the username or the password is wrong, but only gives a vague username or password error.

However, for many programmers, they may not be aware of the “unspoken rules” that may give the user a clear indication of whether the user name is wrong or the password is wrong.

To avoid this, Spring Security hides the username does not exist exception by wrapping it so that when developing, developers only get BadCredentialsException which indicates both that the username does not exist and that the user has entered the wrong password. To ensure that our system is secure enough.

However, for various reasons, sometimes we want to get separate exceptions for non-existent users and incorrect passwords, which requires some simple customization of Spring Security.

1. Source code analysis

First we need to find out why and where the problem occurs.

In Spring Security, there are many classes responsible for user authentication, and the key class involved is AbstractUserDetailsAuthenticationProvider.

This class will be responsible for the authentication of the username and password, specifically in the authenticate method, which is particularly long, so I will only list the code relevant to this article.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        try {
            user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication);
        }
        catch (UsernameNotFoundException ex) {
            if (!this.hideUserNotFoundExceptions) {
                throw ex;
            }
            throw new BadCredentialsException(this.messages
                    .getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
        }
    }
}

The retrieveUser method is to find the user based on the username entered by the user, if not found, it will throw a UsernameNotFoundException, after this exception is caught, it will first determine whether to hide this exception, if not, the original exception will be thrown unchanged, if it needs to be hidden, it will throw a BadCredentialsException is literally an exception for password input errors.

So the heart of the problem becomes the hideUserNotFoundExceptions variable.

This is a Boolean type property that defaults to true, and AbstractUserDetailsAuthenticationProvider also provides a set method for this property.

1
2
3
public void setHideUserNotFoundExceptions(boolean hideUserNotFoundExceptions) {
    this.hideUserNotFoundExceptions = hideUserNotFoundExceptions;
}

It looks like it’s not too hard to modify the hideUserNotFoundExceptions property! Just find the instance of AbstractUserDetailsAuthenticationProvider and call the corresponding set method.

Now the heart of the matter becomes where to get the instance of AbstractUserDetailsAuthenticationProvider?

As you know from the name, AbstractUserDetailsAuthenticationProvider is an abstract class, so its instance is actually an instance of its subclass, who is the subclass? Of course, it’s DaoAuthenticationProvider, which is responsible for user password verification.

Remember this knowledge first, we will use it later.

2. Login process

In order to understand this, we also need to understand a general authentication process for Spring Security, which is also very important.

First of all, you know that authentication in Spring Security is mainly done by AuthenticationManager, which is an interface whose implementation class is ProviderManager. In short, it is the ProviderManager#authenticate method that is specifically responsible for authentication in Spring Security.

But the verification is not done directly by the ProviderManager, the ProviderManager manages a number of AuthenticationProvider, the ProviderManager will call the AuthenticationProvider it manages to complete the verification work as follows Figure.

Login process

On the other hand, ProviderManager is divided into global and local.

When we log in, the local ProviderManager will first come out to verify the user name and password, if the verification is successful, then the user is logged in successfully, if the verification fails, then the parent of the local ProviderManager, that is, the global ProviderManager, will be called to complete the verification. If the global ProviderManager is successful, it means the user is successfully logged in, if the global ProviderManager fails, it means the user failed to log in, as follows.

ProviderManager

OK, with the above knowledge base, let’s analyze what we should do if we want to throw a UsernameNotFoundException.

3. Idea Analysis

First of all, our user verification is done in a local ProviderManager. The local ProviderManager manages a number of AuthenticationProviders, which may contain the DaoAuthenticationProvider we need. Do we need to call the setHideUserNotFoundExceptions method of the DaoAuthenticationProvider here to finish modifying the properties?

No need! Why?

Because when a user logs in, the first thing to do is to check in the local ProviderManager, and if the check is successful, of course, it is best; if the check fails, it will not immediately throw an exception, but will continue to check in the global ProviderManager, so that even if we have thrown a UsernameNotFoundException is useless even if we throw it in the local ProviderManager, because ultimately the decision to throw this exception lies in the global ProviderManager (if the DaoAuthenticationProvider managed by the global ProviderManager does not do any special processing, then the local UsernameNotFoundException thrown in the ProviderManager will eventually be hidden).

So, all we have to do is to get the global ProviderManager, and then get the DaoAuthenticationProvider managed by the global ProviderManager, and then call its setHideUserNotFoundExceptions method to modify the corresponding property values.

Once you understand the principle, the code is simple.

4. Specific Practices

The global ProviderManager is modified in the WebSecurityConfigurerAdapter#configure(AuthenticationManagerBuilder) class, and the AuthenticationManagerBuilder configured here is eventually is used to generate the global ProviderManager, so our configuration is as follows.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
        daoAuthenticationProvider.setHideUserNotFoundExceptions(false);
        InMemoryUserDetailsManager userDetailsService = new InMemoryUserDetailsManager();
        userDetailsService.createUser(User.withUsername("javaboy").password("{noop}123").roles("admin").build());
        daoAuthenticationProvider.setUserDetailsService(userDetailsService);
        auth.authenticationProvider(daoAuthenticationProvider);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .failureHandler((request, response, exception) -> System.out.println(exception))
                .permitAll();

    }

}

The code here is simple.

  • Create a DaoAuthenticationProvider object.
  • Call the DaoAuthenticationProvider object’s setHideUserNotFoundExceptions method of the DaoAuthenticationProvider object and modify the values of the corresponding properties.
  • Configure the user data source for the DaoAuthenticationProvider.
  • Set the DaoAuthenticationProvider to the auth object, auth will be used to generate the global ProviderManager.
  • In another configure method, we’ll just configure the login callback and print an exception message when the login fails.

Next, start the project to test it. Enter an incorrect username and you can see that the IDEA console prints the following message.

1
org.springframework.security.core.userdetails.UsernameNotFoundException:sentinel

UsernameNotFoundException has been thrown.

Reference http://www.enmalvi.com/2021/10/29/springsecurity-badcredentialsexception/

Появление сообщения об ошибке 401 Unauthorized Error («отказ в доступе») при открытии страницы сайта означает неверную авторизацию или аутентификацию пользователя на стороне сервера при обращении к определенному url-адресу. Чаще всего она возникает при ошибочном вводе имени и/или пароля посетителем ресурса при входе в свой аккаунт. Другой причиной являются неправильные настройки, допущенные при администрировании web-ресурса. Данная ошибка отображается в браузере в виде отдельной страницы с соответствующим описанием. Некоторые разработчики интернет-ресурсов, в особенности крупных порталов, вводят собственную дополнительную кодировку данного сбоя:

  • 401 Unauthorized;
  • Authorization Required;
  • HTTP Error 401 – Ошибка авторизации.

Попробуем разобраться с наиболее распространенными причинами возникновения данной ошибки кода HTTP-соединения и обсудим способы их решения.

Причины появления ошибки сервера 401 и способы ее устранения на стороне пользователя

При доступе к некоторым сайтам (или отдельным страницам этих сайтов), посетитель должен пройти определенные этапы получения прав:

  1. Идентификация – получение вашей учетной записи («identity») по username/login или email.
  2. Аутентификация («authentic») – проверка того, что вы знаете пароль от этой учетной записи.
  3. Авторизация – проверка вашей роли (статуса) в системе и решение о предоставлении доступа к запрошенной странице или ресурсу на определенных условиях.

Большинство пользователей сохраняют свои данные по умолчанию в истории браузеров, что позволяет быстро идентифицироваться на наиболее часто посещаемых страницах и синхронизировать настройки между устройствами. Данный способ удобен для серфинга в интернете, но может привести к проблемам с безопасностью доступа к конфиденциальной информации. При наличии большого количества авторизованных регистрационных данных к различным сайтам используйте надежный мастер-пароль, который закрывает доступ к сохраненной в браузере информации.

Наиболее распространенной причиной появления ошибки с кодом 401 для рядового пользователя является ввод неверных данных при посещении определенного ресурса. В этом и других случаях нужно попробовать сделать следующее:

  1. Проверьте в адресной строке правильность написания URL. Особенно это касается перехода на подстраницы сайта, требующие авторизации. Введите правильный адрес. Если переход на страницу осуществлялся после входа в аккаунт, разлогинитесь, вернитесь на главную страницу и произведите повторный вход с правильными учетными данными.
  2. При осуществлении входа с сохраненными данными пользователя и появлении ошибки сервера 401 проверьте их корректность в соответствующих настройках данного браузера. Возможно, авторизационные данные были вами изменены в другом браузере. Также можно очистить кэш, удалить cookies и повторить попытку входа. При удалении истории браузера или очистке кэша потребуется ручное введение логина и пароля для получения доступа. Если вы не помните пароль, пройдите процедуру восстановления, следуя инструкциям.
  3. Если вы считаете, что вводите правильные регистрационные данные, но не можете получить доступ к сайту, обратитесь к администратору ресурса. В этом случае лучше всего сделать скриншот проблемной страницы.
  4. Иногда блокировка происходит на стороне провайдера, что тоже приводит к отказу в доступе и появлению сообщения с кодировкой 401. Для проверки можно попробовать авторизоваться на том же ресурсе с альтернативного ip-адреса (например, используя VPN). При подтверждении блокировки трафика свяжитесь с провайдером и следуйте его инструкциям.

Некоторые крупные интернет-ресурсы с большим количеством подписчиков используют дополнительные настройки для обеспечения безопасности доступа. К примеру, ваш аккаунт может быть заблокирован при многократных попытках неудачной авторизации. Слишком частые попытки законнектиться могут быть восприняты как действия бота. В этом случае вы увидите соответствующее сообщение, но можете быть просто переадресованы на страницу с кодом 401. Свяжитесь с администратором сайта и решите проблему.

Иногда простая перезагрузка проблемной страницы, выход из текущей сессии или использование другого веб-браузера полностью решают проблему с 401 ошибкой авторизации.

Ошибка 401 - отказ в доступе

Устранение ошибки 401 администратором веб-ресурса 

Для владельцев сайтов, столкнувшихся с появлением ошибки отказа доступа 401, решить ее порою намного сложнее, чем обычному посетителю ресурса. Есть несколько рекомендаций, которые помогут в этом:

  • Обращение в службу поддержки хостинга сайта. Как и в случае возникновения проблем с провайдером, лучше всего подробно описать последовательность действий, приведших к появлению ошибки 401, приложить скриншот.
  • При отсутствии проблем на стороне хостинг-провайдера можно внести следующие изменения в настройки сайта с помощью строки Disallow:/адрес проблемной страницы. Запретить индексацию страницам с ошибкой в «rоbоts.txt», после чего добавить в файл «.htассеss» строку такого типа:
Redirect 301 /oldpage.html http://site.com/newpage.html.

Где в поле /oldpage.html прописывается адрес проблемной страницы, а в http://site.com/newpage.html адрес страницы авторизации.

Таким образом вы перенаправите пользователей со всех страниц, которые выдают ошибку 401, на страницу начальной авторизации.

  • Если после выполнения предыдущих рекомендаций пользователи при попытках авторизации все равно видят ошибку 401, то найдите на сервере файл «php.ini» и увеличьте время жизни сессии, изменив значения следующих параметров: «session.gc_maxlifetime» и «session.cookie_lifetime» на 1440 и 0 соответственно.
  • Разработчики веб-ресурсов могут использовать более сложные методы авторизации и аутентификации доступа для создания дополнительной защиты по протоколу HTTP. Если устранить сбой простыми методами администрирования не удается, следует обратиться к специалистам, создававшим сайт, для внесения соответствующих изменений в код.

Хотя ошибка 401 и является проблемой на стороне клиента, ошибка пользователя на стороне сервера может привести к ложному требованию входа в систему. К примеру, сетевой администратор разрешит аутентификацию входа в систему всем пользователям, даже если это не требуется. В таком случае сообщение о несанкционированном доступе будет отображаться для всех, кто посещает сайт. Баг устраняется внесением соответствующих изменений в настройки.

Дополнительная информация об ошибке с кодом 401

Веб-серверы под управлением Microsoft IIS могут предоставить дополнительные данные об ошибке 401 Unauthorized в виде второго ряда цифр:

  • 401, 1 – войти не удалось;
  • 401, 2 – ошибка входа в систему из-за конфигурации сервера;
  • 401, 3 – несанкционированный доступ из-за ACL на ресурс;
  • 401, 501 – доступ запрещен: слишком много запросов с одного и того же клиентского IP; ограничение динамического IP-адреса – достигнут предел одновременных запросов и т.д.

Более подробную информацию об ошибке сервера 401 при использовании обычной проверки подлинности для подключения к веб-узлу, который размещен в службе MS IIS, смотрите здесь. 

Следующие сообщения также являются ошибками на стороне клиента и относятся к 401 ошибке:

  • 400 Bad Request; 
  • 403 Forbidden; 
  • 404 Not Found;
  • 408 Request Timeout.

Как видим, появление ошибки авторизации 401 Unauthorized не является критичным для рядового посетителя сайта и чаще всего устраняется самыми простыми способами. В более сложной ситуации оказываются администраторы и владельцы интернет-ресурсов, но и они в 100% случаев разберутся с данным багом путем изменения настроек или корректировки html-кода с привлечением разработчика сайта. 

The HyperText Transfer Protocol (HTTP) 401 Unauthorized response status code indicates that the client request has not been
completed because it lacks valid authentication credentials for the requested resource.

This status code is sent with an HTTP WWW-Authenticate response header that contains
information on how the client can request for the resource again after prompting the user for authentication credentials.

This status code is similar to the 403 Forbidden status code, except that in situations resulting in this
status code, user authentication can allow access to the resource.

Status

Example response

HTTP/1.1 401 Unauthorized
Date: Wed, 21 Oct 2015 07:28:00 GMT
WWW-Authenticate: Basic realm="Access to staging site"

Specifications

Specification
HTTP Semantics
# status.401

Browser compatibility

BCD tables only load in the browser

See also

I just updated and now it doesn’t work.¶

It’s just a blank white screen, nothing will load when I refresh. See.

Server Troubleshooting Script¶

If you’ve asked for help in #support please run this, and send a screenshot at the top of the thread created for troubleshooting your issue.

Blur your domains if you desire privacy (or DM the person that’s helping you to make everyones life easier).

First, ensure that dig is installed via the dnsutils package:

sudo apt update && sudo apt install -y dnsutils

Next, download and run the troubleshooting script:

wget -N https://raw.githubusercontent.com/amidaware/tacticalrmm/develop/troubleshoot_server.sh
chmod +x troubleshoot_server.sh
./troubleshoot_server.sh

Note

If you’re working with a support person please provide the full script output. If you don’t want to post publicly, feel free to DM the person working with you in Discord #support channel

Make sure DNS (name resolution) was setup properly¶

From the agent¶

Open command prompt:

ping rmm.example.com
ping api.example.com
ping mesh.example.com

The IP address for all 3 should reflect your Tactical RMM server.

Problems after new server install¶

In the very unlikely event you have issues after install please wipe the box and install again (following all the steps including downloading the install script but not running it yet) use the following command which will log the install progress and if you continue to have issues will assist with support of the installation.

bash -x install.sh 2>&1 | tee install.log

Note

Logging of installs isn’t desirable as it logs extremely sensitive information which is why this isn’t done by default! Do not post the raw log publicly only provide it if requested and then by dm only. Authorized users in Discord are: @BurningTimes#1938 @sadnub#6992 @dinger1986#1734 @silversword#9652

«Bad credentials» error when trying to login to the web UI¶

If you are sure you are using the correct credentials and still getting a «bad credentials» error, open your browser’s dev tools (Ctrl+Shift+J on Chrome) and check the Console tab to see the real error.

It will most probably be a CORS error which means you need to check your DNS settings and make sure whatever computer you’re trying to access the UI from resolves your 3 subdomains to the correct IP of the server running the RMM (public IP if running in the cloud, or private IP if running behind NAT).

If you see an error about SSL or certificate expired, then your Let’s Encrypt cert has probably expired and you’ll need to renew it.

Refer to the Let’s Encrypt cert renewal instructions here.

Agents not installing or updating¶

The most common problem we’ve seen of agents not installing or updating is due to Antivirus blocking the updater executable.

Windows Defender will 100% of the time block the updater from running unless an exclusion is set.

Refer to the Agent Installation instructions for AV exceptions to set and manually doing an agent update with logging to troubleshoot further.

Agents will also not automatically update if they are too old.

If you have agents that are relatively old, you will need to uninstall them manually and reinstall using the latest version.

The mesh installer is created at time of install. Make sure it’s working by running this on your TRMM server.

Check TRMM connection to MeshCentral

Standard Install docker

/rmm/api/env/bin/python /rmm/api/tacticalrmm/manage.py check_mesh
sudo docker compose exec tactical-backend python manage.py check_mesh

if sharing

Warning

As of v0.12.0 Error 1005 usually means something doesn’t match and / or the mesh username has to be all lower case.
If you customize the «Mesh Device Group Name» in Tactical’s settings you MUST also manually match that Mesh Group in mesh itself because you must understand.

Collect Update debug logs for troubleshooting agents that don’t update

Make sure TRMM can connect to mesh

Agents not checking in or showing up / General agent issues¶

Eg. Agent Boot time: 53 years ago

These are NATS problems. Try the quick fixes first:

From Admin Web Interface¶

First, reload NATS from Tactical’s web UI:
Tools > Server Maintenance > Reload Nats Configuration

If that doesn’t work, check each part starting with the server:

Server SSH login¶

Reload NATS:

/rmm/api/env/bin/python /rmm/api/tacticalrmm/manage.py reload_nats
sudo systemctl restart nats.service

Look at NATS service errors (make sure it’s running):

sudo systemctl status nats.service

If NATS isn’t running see detailed reason why it isn’t:

sudo systemctl stop nats.service
nats-server -DVV -c /rmm/api/tacticalrmm/nats-rmm.conf

Fix the problem, then restart NATS:

sudo systemctl restart nats.service

From Agent Install¶

Open CMD as admin on the problem computer and stop the agent services:

Run the tacticalrmm service manually with debug logging:

"C:Program FilesTacticalAgenttacticalrmm.exe" -m rpc -log debug -logto stdout

This will print out a ton of info. You should be able to see the error from the debug log output.

Please then copy / paste the logs and post them either in our Discord support chat, or create a github issue.

If all else fails, simply uninstall the agent either from control panel or silently with "C:Program FilesTacticalAgentunins000.exe" /VERYSILENT and then reinstall the agent.

All other errors¶

First, run the update script with the --force flag.

This will fix permissions and reinstall python / node packages that might have gotten corrupted.

Check the debug log from the web UI: File > Debug Log

Open your browser’s dev tools (Ctrl+Shift+J on Chrome) and check the Console tab for any errors.

Check all the systemd services that the rmm uses to function and check to make sure they’re all active / running and enabled:

sudo systemctl status rmm.service
sudo systemctl status daphne.service
sudo systemctl status celery.service
sudo systemctl status celerybeat.service
sudo systemctl status nginx.service
sudo systemctl status nats.service
sudo systemctl status nats-api.service
sudo systemctl status meshcentral.service
sudo systemctl status mongod.service
sudo systemctl status postgresql.service
sudo systemctl status redis-server.service

Or you can use systemctl --failed to see any failed services on your machine.

Read through the log files in the following folders and check for errors:

/rmm/api/tacticalrmm/tacticalrmm/private/log
/var/log/celery

Using Cloudflare DNS¶

  • rmm.example.com can be proxied.

  • api.example.com can be proxied when using (the default) agent configuration which utilizes websockets.

  • mesh.example.com can be proxied with the caveat that Mesh checks the cert presented to the agent is the same one on the server. I.e. no MITM. You’ll need to copy Cloudflare’s edge cert (they call it Origin Server) to your server if you want to proxy this domain.

If you’re getting Invalid group id at the end of the install you’re probably doing something wrong / wrong IP for api.

Testing network connectivity between agent and server¶

Using PowerShell, make sure you can connect to 443 from agent to server:

Test-NetConnection -ComputerName api.example.com -Port 443

Check your SSL certs to make sure they are what they should be (no proxy stuff): https://www.digicert.com/help/

Are you trying to use a reverse proxy to share your single public IP with multiple services on 443? This is complicated and unsupported by Tactical RMM. Test your setup.

Take Control or Remote Background missing button / can’t connect¶

This is a MeshCentral connection problem.

  1. Don’t use Firefox (test in vanilla Chrome first).
  2. Open mesh.domain.com and see if the agent is listed there.
  3. If you don’t see your agent (or it’s offline), restart TRMM server (or service).
  4. Restart Mesh Agent on client PC.
  5. Check again. Still not appearing in mesh.domain.com in Mesh go to «My Server» > Trace tab > Click tracing button > Check MeshAgent traffic.
  6. Restart Mesh Agent on client PC. You should see something in trace like mesh trace.
  7. If you don’t, you have firewall / connectivity issues (open mesh.domain.com from agent and troubleshoot. You aren’t using a proxy right?).

Need to recover your Mesh token?¶

Login to server with SSH and run:

node /meshcentral/node_modules/meshcentral --logintokenkey

Mesh Agent not connecting to server¶

When agents don’t show up in your Mesh console (after logging into https://mesh.EXAMPLE.COM), and all data is blank. Your AV has most likely blocked the agent.

Mesh Not Connecting

Error 500¶

These are always logged to /rmm/api/tacticalrmm/tacticalrmm/private/log/django_debug.log use this to check.

Can’t login on server after first setup¶

You’re sure you’re typing in everything right, giving it 2FA code, and getting error 400 login error.

TOTP is time sensitive, check your time/NTP and make sure it’s right! :)

Error 0:¶

If you’re trying to login check dns, check server and client time, and check your certs.

executable file not found in %PATH%¶

This error can show up for PowerShell or choco.

  • exec: "Powershell": executable file not found in %PATH%
  • exec: "choco.exe": executable file not found in %PATH%
  • choco : The term 'choco' is not recognized as the name of a cmdlet

Run the Win_Powershell_TestPATH.bat script to gather information about your environment. This script will output either ExpandString or String. See Microsoft’s docs for details.

  • ExpandString (REG_EXPAND_SZ) means %SystemRoot% will expand to C:Windows. Reboot and choco will most likely work.
  • String (REG_SZ) means %SystemRoot% will not be expanded. Changing the registry value type will most likely work.

Note

If your path does not have Path variables like %SystemRoot%, the registry type does not matter because the paths are already expanded.

If the script outputs «String», changing the registry type and restarting the Tactical service will most likely work. This script will output the value type and the $PATH. Make note of the $PATH because Set-ItemProperty needs the value to change the type. Run this as administrator and uncomment Set-ItemProperty to change the registry type to ExpandString. Run the first two commands to get the type and $PATH to make sure everything is good. Restart the TacticalRMM service and try the command again.

$kind = (Get-Item -Path 'Registry::HKEY_LOCAL_MACHINESystemCurrentControlSetControlSession ManagerEnvironment').GetValueKind('PATH')
Write-Output "Path kind before the change: ${kind}"

$path = Get-ItemPropertyValue -Path 'Registry::HKEY_LOCAL_MACHINESystemCurrentControlSetControlSession ManagerEnvironment' -Name Path
Write-Output "Path before changing the type:", $path

Write-Output "Changing the registry key type"
# Needs to be run as administrator
# Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINESystemCurrentControlSetControlSession ManagerEnvironment' -Name PATH -Value $path -Type ExpandString
Write-Output ""

$kind = (Get-Item -Path 'Registry::HKEY_LOCAL_MACHINESystemCurrentControlSetControlSession ManagerEnvironment').GetValueKind('PATH')
Write-Output "Path kind after the change: ${kind}"

$path = Get-ItemPropertyValue -Path 'Registry::HKEY_LOCAL_MACHINESystemCurrentControlSetControlSession ManagerEnvironment' -Name Path
Write-Output "Path after changing the type:", $path

Issues with agents offline after reboot or new install on AWS and other cloud platforms using cloudinit or similar¶

  1. Run cat /etc/hosts
  2. If the output shows that the hosts file is managed by another process follow the instructions to change the config.
  3. Add in your api, rmm and mesh urls on the line for 127.0.1.1 in the hosts file
  4. Save the hosts file
  5. Restart services or run update.sh --force

Понравилась статья? Поделить с друзьями:
  • Backgroundtaskhost exe системная ошибка
  • Backgroundtaskhost exe ошибка приложения
  • Back ups pro 1200 ошибка f02
  • Back ups es 525 ошибки
  • Back 4 blood ошибка unknown file version