mitreid-connect / OpenID-Connect-Java-Spring-Server

An OpenID Connect reference implementation in Java on the Spring platform.
Other
1.48k stars 765 forks source link

Issues setting up openid-connect-server-webapp overlay #1431

Open drkarl opened 5 years ago

drkarl commented 5 years ago

I am integrating the openid-connect-server-webapp in my application. I created a new subproject using the overlay method described in the documentation. After fixing all the issues (conflicts with beans already defined elsewhere on the project, fixing the mysql db scripts and so on), I finally can start the application with no errors and the mitre openid connect endpoints are available.

In my opinion the documentation is insufficient and lacks examples of requests with full workflow. I have read the OpenId specs and also articles in various sites. This is to protect an API that will be called by third parties, so I'm assuming the flow which makes sense would be the client credentials grant?

My understanding is:

1) Discovery endpoint (OPTIONAL if we know the information out-of-band). This endpoint doesn't require authentication Retrieve metadata about the Identity Server like issuer name, key material, supported scopes etc. GET /.well-known/openid-configuration

2) Dynamic Client Registration endpoint With information from discovery endpoint, register a new client. That will give us the client_id and client_secret, which can be obtained by out-of-band methods. POST /register HTTP/1.1

We provide information about the client name, scopes and grant_types on the body.

3) Authorization endpoint Use the client credentials (client credentials grant) on the authorization endpoint to retrieve a code

4) Token endpoint Use the code retrieved in the authorization endpoint and exchange it for an id_token and an access_token

For now I'm trying to use the existing demo client (client_id=client and client_secret=secret) so I think I can skip steps 1 and 2. I tried using Basic authentication with the authorization endpoint, like Basic <base64 encoded "clientId:clientSecret">. Also considered using the Bearer token authentication with an initial token, that can be provided out of band, but not sure how would I register that initial token so that the server can be authenticated using it.

When I try to send a request to the OIDC endpoints, it reaches the breakpoints but the principal is null, which means that

Authentication auth = SecurityContextHolder.getContext().getAuthentication();

auth is null as well.

I see on OIDCAuthenticationToken that it creates the principal from the sub (subject) and iss (issuer), but that part of the code on UserInfoInterceptor is not reached because auth is null.

I would greatly appreciate some insight into how could I get it working with the client credentials grant, and also how would an initial token (provided out-of-band) be registered/used so that it can authenticate that first request. The initial bearer token maybe makes more sense with the client registration endpoint, then that endpoint gives you the client_id and client_secret which you can then use to get a code and finally your access_token.

kabiliravi commented 5 years ago

@drkarl I dived into the code and made remarkable changes on the proposed version 2.0.0. I might be able to help you. To help you better and being in the same page, I ask you to follow the instructions that I give you. The way that I always test OpenID Connect Server is through standalone postman (Not chrome based plugin). So the first step I ask you to do, is to try to generate a new access token. That way you can make sure you have setup your registered clients correctly. Please let me know if you have issues there.

kabiliravi commented 5 years ago

@drkarl You can use https://github.com/kabiliravi/OpenID-Connect-Java-Spring-Server/tree/2.0.0 I fixed a lot of things there including the mysql

drkarl commented 5 years ago

Thanks for your reply, @kabiliravi. Yes, I was already using Postman.

Regarding the mysql scripts, I had already fixed that, I used the changes in this PR https://github.com/mitreid-connect/OpenID-Connect-Java-Spring-Server/pull/1291 After that, I also had the problem described on this issue: https://github.com/mitreid-connect/OpenID-Connect-Java-Spring-Server/issues/753 I fixed it changing the VARCHARs which were too long to TEXT.

Your changes are based on master, here's a diff https://github.com/mitreid-connect/OpenID-Connect-Java-Spring-Server/compare/master...kabiliravi:master but the version I'm using from Maven Central is 1.3.2 so it's the 1.3.x branch

Anyway I see you're creating the temporary tables, but on the pull request I mentioned above, the create temporary tables are on a separate script loading_temp_tables.sql, like it is on the folders for other databases, at least on the 1.3.x branch.

Also, review your .gitignore, you added a Mac OS specific file, .DS_STORE

drkarl commented 5 years ago

I haven't registered any new client for now with the Dynamic Registration endpoint, I am initially trying to use the default demo client inserted on the database with the clients.sql script, which has client_id='client' and client_secret='secret'.

I'm still trying to understand what is the suggested/preferred workflow. The /authorize endpoint tries to redirect to a login page so that the user logs in, but what about machine-to-machine authentication? For that scenario I modified the spring security configuration to enable basic authentication to at least send the credentials with an Authorization header for the /authorize endpoint. So the workflow I image makes sense would be:

1) Send request to /authorize endpoint with basic authentication to avoid redirection to login page, which should return the authorization code 2) Send request with the authorization code to /token endpoint which will return access/id tokens as requested. 3) Send access token to access protected resources

The problem is that, although enabling basic authentication worked fine for some endpoints, like Configuration endpoint (/.well-known/openid-configuration) Clients endpoint (api/clients) Tokens access endpoint (api/tokens/access)

The authorization endpoint, with a request that would be something like

/authorize?client_id=client&response_type=code&scope=openid&redirect_uri=http%3A%2F%2Flocalhost:9084%2Fmy-context%2Foidc

redirects to /oauth/confirm_access which is the controller OAuthConfirmationController, validates all the parameters and then forwards onto the "approve" view, which is /WEB-INF/views/approve.jsp for the user to grant access

That is fine with the implicit flow, or maybe the authorization code flow, but it's a problem if you expect to authenticate without user intervention with the client credentials flow or the resource owner flow.

Also, even if you wanted to use say or authorization code flow, how would you test that with Postman if it expects to show an html (jsp) page for the user to grant access?

I had another problem, that is that in addition to the application context I have a servlet context because this is a subproject of a larger project, so let's call the context my-context and the servlet context oidc (for OpenID Connect) for anonimization purposes, so the url of the IdP server is http://localhost:9084/my-context/oidc so the authorize endpoint would be http://localhost:9084/my-context/oidc/authorize. The endpoint is hit fine but when it tries to redirect to /oauth/confirm_access it doesn't use the servlet context so it tries to use http://localhost:9084/my-context/oauth/confirm_access. Fixed that by adding user-approval-page attribute on in authz-config.xml, and then it works fine and hits OAuthConfirmationController.confirmAccess(). The problem is that when it tries to redirect to render the approve view it returns a 404, even if the view is indeed in /WEB-INF/views/approve.jsp on the deployed WAR.

drkarl commented 5 years ago

I see last commit was 5 months ago so the main developers have probably moved on to other projects. I'll invoke them in case they have some thoughts or advice.

@jricher @aanganes any ideas would be greatly appreciated!!

rhinmass commented 5 years ago

You can disable the user confirmation page by whitelisting the client