Custom controller anonymous access

Hi,

I am trying to access custom controller without token,
I am calling a custom controller to get the active token for user login id Ex: “anonymousAccessUser” it will give me if there is any active token in the database which is not expired for this user and if no active token present in the database then I am creating a new token and returning the response back which is working perfect.

But I want to access this API(custom controller) without passing any oAuth token. Below is the code for your reference please help me to correct the thing where i am making mistake

portal-security-spring.xml

<security:http pattern="/rest/myapi/**"
                   create-session="stateless"
                   entry-point-ref="oauthAuthenticationEntryPoint"
                   xmlns="http://www.springframework.org/schema/security">
        <intercept-url pattern="/rest/myapi/**" access="true"/>
        <anonymous enabled="true"/>
        <csrf disabled="true"/>
        <cors configuration-source-ref="cuba_RestCorsSource"/>
        <custom-filter ref="resourceFilter" before="PRE_AUTH_FILTER"/>
        <custom-filter ref="cuba_AnonymousAuthenticationFilter" after="PRE_AUTH_FILTER"/>
    </security:http>

My custom controller

@RestController
@RequestMapping("/myapi")
public class MyController {

    @GetMapping("/getUserTokenDetails")
    public String getUserTokenDetails() {
        try {
            String userLogin = "anonymousAccessUser"; //user created with this login id
            UserTokenDTO tokenDetails = utilityService.getAnonymousToken(userLogin); //calling service method which returns active token for this user
if(tokenDetails == null){
//generating new token if no active token found in databse
                OAuthTokenIssuer.OAuth2AccessTokenResult tokenResult = oAuthTokenIssuer.issueToken(userLogin,
                        messageTools.getDefaultLocale(), Collections.emptyMap());
                OAuth2AccessToken accessToken = tokenResult.getAccessToken();

                return accessToken.getValue();
            } else {
//return existing active token
                return tokenDetails.getAccess_token();
            }

        } catch (Exception ex) {
            return "No active token found"+ex;
        }
    }

Service bean method to return active token if any

@Override
public UserTokenDTO getAnonymousToken(String userLogin) throws Exception{
    String query = "SELECT ACCESS_TOKEN_VALUE, EXPIRY, AUTHENTICATION_KEY, USER_LOGIN FROM SYS_REST_API_TOKEN "
            + " WHERE USER_LOGIN = '"+ userLogin +"' AND EXPIRY > CURRENT_TIMESTAMP "
            + " ORDER BY EXPIRY DESC ";
    Map<String, String> params = new HashMap<>();
    
    log.debug("Executing query : "+query);
    List<UserTokenDTO> userTokenList = entityManagerService.getUserTokenDetails(query, params);
    return userTokenList.isEmpty() ? null : userTokenList.get(0);
}

When i run this API it says "java.lang.SecurityException: No security context bound to the current thread"
I feel when we are calling service method getAnonymousToken(String userLogin) it is asking for token.

Do we need to make any changes in the “portal-security-spring.xml” configuration

Hi,
2 thoughts:

  1. If you don’t need any security for your endpoints, maybe you can disable it?
<security:http pattern="/rest/myapi/**" security="none"/>
  1. Check that your service method uses system authentication: System Authentication - CUBA Platform. Developer’s Manual
1 Like

Thanks for the reply @gorbunkov I will try to make the changes you suggested and update you back

Hi,

I tried this in cuba version 6.9.4 but I keep getting following error:

{
    "error": "unauthorized",
    "error_description": "An Authentication object was not found in the SecurityContext"
}

Am I missing something??

Thanks

Hi @shashanksinghal,

Which type of request you are making?
GET or POST?

Regards
Shanur

Hi Max,
So for the 2 ways you mentioned, what is the difference about use case while using them?
For which kind of case, we use #1 and which case for #2?
Any security issue needs to be concerned?

If I need to develop some API which is public, for example, user self register; public get method which used in product description html, user manual,etc?

Hi,
That were not two cases, that were two parts of solving the problem: first, authentication for given endpoint must be disabled, and second, when some operations that require CUBA system authentication are performed in the accessed controller, then such an authentication must be performed (see the documentation link)
If your case is serving a static content (documentation, html pages and so on) then you may use DispatcherServiet for this.

  1. Create modules/web/web/website directory and add static resources there
  2. Modify your web-dispatcher-spring.xml file:
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-4.3.xsd
           http://www.springframework.org/schema/mvc
           http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <mvc:resources mapping="/**" location="/website/" />
    <mvc:view-controller path="/" view-name="index.html"/>
</beans>

By default dispatcher servlet is set up on http://localhost:8080/app/dispatch/, so if you access http://localhost:8080/app/dispatch/myfile.pdf you’ll get the myfile.pdf file located in the website directory.

Is it possible for JSP pages (except static content) as well?