openshift / openshift-restclient-java

Other
78 stars 112 forks source link

getToken() and getAuthScheme() return null and isAuthorized() returns exception. #439

Closed gaurav-dhoot closed 4 years ago

gaurav-dhoot commented 4 years ago

I have minishift setup in my laptop. I wanted to write a piece of code where the user can only continue if he is authorized on minishift. To my surprise, I get an exception when I try this. Also, I tried to retrieve the token and authScheme which are again null. I do get the userName and Password when I give appropriate methods.

Here is the piece of code I used: IClient client=new ClientBuilder("https://192.168.99.105:8443").withUserName("developer").withPassword("SomeRandomString").build(); System.out.println(client.getServerReadyStatus()); System.out.println(client.getAuthorizationContext().getAuthorizationDetails().getRequestTokenLink()); System.out.println(client.getAuthorizationContext().getToken()); System.out.println(client.getAuthorizationContext().getAuthScheme()); System.out.println(client.getAuthorizationContext().isAuthorized());

Here is the output: ok https://192.168.99.105:8443/oauth/token/request null null log4j:WARN No appenders could be found for logger (com.openshift.internal.restclient.ApiTypeMapper). log4j:WARN Please initialize the log4j system properly. log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info. Exception in thread "main" java.lang.NoSuchMethodError: org.jboss.dmr.ModelNode.has([Ljava/lang/String;)Z at com.openshift.internal.util.JBossDmrExtentions.asString(JBossDmrExtentions.java:263) at com.openshift.internal.restclient.ApiTypeMapper$ApiGroup.getName(ApiTypeMapper.java:228) at com.openshift.internal.restclient.ApiTypeMapper$ApiGroup.(ApiTypeMapper.java:209) at com.openshift.internal.restclient.ApiTypeMapper.lambda$getApiGroups$4(ApiTypeMapper.java:163) at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382) at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482) at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472) at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708) at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499) at com.openshift.internal.restclient.ApiTypeMapper.getApiGroups(ApiTypeMapper.java:164) at com.openshift.internal.restclient.ApiTypeMapper.init(ApiTypeMapper.java:123) at com.openshift.internal.restclient.ApiTypeMapper.isSupported(ApiTypeMapper.java:111) at com.openshift.internal.restclient.URLBuilder.buildWithNamespaceInPath(URLBuilder.java:145) at com.openshift.internal.restclient.URLBuilder.build(URLBuilder.java:132) at com.openshift.internal.restclient.DefaultClient.execute(DefaultClient.java:250) at com.openshift.internal.restclient.DefaultClient.execute(DefaultClient.java:221) at com.openshift.internal.restclient.DefaultClient.execute(DefaultClient.java:209) at com.openshift.internal.restclient.DefaultClient.get(DefaultClient.java:332) at com.openshift.internal.restclient.authorization.AuthorizationContext.isAuthorized(AuthorizationContext.java:65) at LoginToOpenshift.main(Connect.java:29)

adietish commented 4 years ago

Hi @gaurav-dhoot

I'm not able to see what step within your pasted code triggers the exception. Can you please reports what's in Connect at line 29? I also see that your line numbers dont match what I see in our master. It looks as if you're not using the latest version (8.1.1.Final or 8.1.2-SNAPSHOT) of the library?

Cheers André

gaurav-dhoot commented 4 years ago

Hi @adietish,

Connect is the name of my class :-). System.out.println(client.getAuthorizationContext().isAuthorized()); causes an exception. All the other methods return a null value. Looks like I am using a very outdated version of you project. I am using the 5.9.6 version, that could definitely cause the problem. Anyway, I will try it again with the updated project this time and check if it still works or not.

Cheers, Gaurav Dhoot

gaurav-dhoot commented 4 years ago

Hi @adietish,

I have tried using the 8.1.1.FINAL version of the library. Again, the response to the getToken() is null and when I try isAuthorized(), it throws an exception, however a different one this time.

Below is the code and the console output of the same. public class testing {

public static void main(String[] args) {
    IClient client=new ClientBuilder("https://192.168.99.105:8443/").withUserName("system:admin").withPassword("sfsf").build();
    System.out.println(client.getServerReadyStatus());
    System.out.println(client.getAuthorizationContext().getToken());
    System.out.println(client.getAuthorizationContext().isAuthorized());
}

}

Output: SLF4J: No SLF4J providers were found. SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#noProviders for further details. ok null Exception in thread "main" com.openshift.restclient.authorization.ResourceForbiddenException: users "~" is forbidden: User "system:anonymous" cannot get users at the cluster scope: User "system:anonymous" cannot get users at the cluster scope users "~" is forbidden: User "system:anonymous" cannot get users at the cluster scope: User "system:anonymous" cannot get users at the cluster scope at com.openshift.internal.restclient.okhttp.ResponseCodeInterceptor.createOpenShiftException(ResponseCodeInterceptor.java:119) at com.openshift.internal.restclient.okhttp.ResponseCodeInterceptor.intercept(ResponseCodeInterceptor.java:69) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:87) at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.kt:184) at okhttp3.RealCall.execute(RealCall.kt:66) at com.openshift.internal.restclient.DefaultClient.request(DefaultClient.java:314) at com.openshift.internal.restclient.DefaultClient.execute(DefaultClient.java:306) at com.openshift.internal.restclient.DefaultClient.execute(DefaultClient.java:271) at com.openshift.internal.restclient.DefaultClient.execute(DefaultClient.java:239) at com.openshift.internal.restclient.DefaultClient.execute(DefaultClient.java:222) at com.openshift.internal.restclient.DefaultClient.get(DefaultClient.java:406) at com.openshift.internal.restclient.authorization.AuthorizationContext.isAuthorized(AuthorizationContext.java:63) at operator.restapi.testing.main(testing.java:12)

I have seen that another user had faced a similar issue for the getToken(), but it worked for him when he places isAuthorized() above the getToken(). However, this does not wok for me.

Regards, Gaurav Dhoot

adietish commented 4 years ago

Hi @gaurav-dhoot

thx for reporting all these details, I'll try to reproduce your issue. The 1st thing that I stumble upon is that you get a ResourceForbiddenException. There are 2 possible explanations: Either your credentials are bad or we have a problem in the client where an url is requested without credentials where those are required.

gaurav-dhoot commented 4 years ago

Hi @adietish,

Thanks for the acknowledgement. To rule out the bad credentials, I am running a minishift cluster and so, it should not actually deny authentication whatever the password be. Also, I have tried using another username with all the privileges but still get the same exception. So looks like there has to be a problem with the URL. Anyway, you could tell me some more steps (if needed) to verify if the issue is actually on my side or the project.

adietish commented 4 years ago

Hi @guarav-dhoot

I can reproduce the issue using a minishift that I run locally. So I'll dig into it, trying to understand what's happening. Another thing I noticed is that the following is wrong: .withUserName("system:admin").withPassword("sfsf") it should be: .withUserName("system").withPassword("admin") Nevertheless, when correcting this, I still get an exception which obviously is a bug. I get the following exception:

Exception in thread "main" com.openshift.restclient.authorization.ResourceForbiddenException: users "~" is forbidden: User "system:anonymous" cannot get users at the cluster scope: User "system:anonymous" cannot get users at the cluster scope users "~" is forbidden: User "system:anonymous" cannot get users at the cluster scope: User "system:anonymous" cannot get users at the cluster scope
    at com.openshift.internal.restclient.okhttp.ResponseCodeInterceptor.createOpenShiftException(ResponseCodeInterceptor.java:119)
    at com.openshift.internal.restclient.okhttp.ResponseCodeInterceptor.intercept(ResponseCodeInterceptor.java:69)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:112)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:87)
    at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.kt:184)
    at okhttp3.RealCall.execute(RealCall.kt:66)
    at com.openshift.internal.restclient.DefaultClient.request(DefaultClient.java:314)
    at com.openshift.internal.restclient.DefaultClient.execute(DefaultClient.java:306)
    at com.openshift.internal.restclient.DefaultClient.execute(DefaultClient.java:271)
    at com.openshift.internal.restclient.DefaultClient.execute(DefaultClient.java:239)
    at com.openshift.internal.restclient.DefaultClient.execute(DefaultClient.java:222)
    at com.openshift.internal.restclient.DefaultClient.get(DefaultClient.java:406)
    at com.openshift.internal.restclient.authorization.AuthorizationContext.isAuthorized(AuthorizationContext.java:63)
gaurav-dhoot commented 4 years ago

Hi @adietish,

Guess that is right. Maybe I have sent you a copy of one of my trials. But as we can see, this looks to be an internal issue.

adietish commented 4 years ago

Hi @gaurav-dhoot

turns out that the request to discover the auth endpoint already fails with 403/Forbidden for me (AuthorizationEndpoints.getAuthorizationEndpoint()). Worth to be noted is that this url (<minishift-host>/.well-known/oauth-authorization-server) is supposed to be unprotected and that the request is thus done without username/password.

$ curl -k https://192.168.64.174:8443//.well-known/oauth-authorization-server
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "forbidden: User \"system:anonymous\" cannot get path \"//.well-known/oauth-authorization-server\": User \"system:anonymous\" cannot \"get\" on \"//.well-known/oauth-authorization-server\"",
  "reason": "Forbidden",
  "details": {},
  "code": 403
}%

I'm digging further keeping you posted.

adietish commented 4 years ago

Hi @gaurav-dhoot I have found a solution where I don't get the exception any more. I simply get a use the default authorization endpoint if discovering fails as explained above. I created pull request #442 with the potential fix. Maybe you want to try it? Retrieving the token before asking about being authorized (#isAuthorized) still reports null because only #isAuthorization triggers the authentication. This is another flaw worth fixing. For now, getting the token after querying the authorization state works:

System.out.println("is authorized: " + client.getAuthorizationContext().isAuthorized());
System.out.println("token: " + client.getAuthorizationContext().getToken());

Here's my output:

is authorized: true
token: ARq4IUX5pOUIXXXXXXXXXXXXXX (obfuscated)
adietish commented 4 years ago

hi @gaurav-dhoot

i merged the changed to current master and deployed 8.1.2-SNAPSHOT to our maven repository at https://repository.jboss.org/. You should be able to consume it by bumping your dependency 8.1.2-SNAPSHOT. It should fix your issue. Please reopen this issue if you can't confirm this or ack here if it does. Thanks!

adietish commented 4 years ago

We published 8.1.2.Final which includes the above fix.