spec-first / connexion

Connexion is a modern Python web framework that makes spec-first and api-first development easy.
https://connexion.readthedocs.io/en/latest/
Apache License 2.0
4.5k stars 766 forks source link

Anyone tried OpenId? #694

Open WimDH opened 6 years ago

WimDH commented 6 years ago

Description

I tried to use OpenId for secure my endpoints, but when the security is not applied. My endpoint returned it's result without the use of my token.

I cloned the dev-2.0 branch and used the hello example.

My swagger config file:

openapi: "3.0.0"

info:
  title: Hello World
  version: "1.0"
servers:
  - url: http://localhost:9090/v1.0

paths:
  /greeting/{name}:
    post:
      summary: Generate greeting
      description: Generates a greeting message.
      operationId: hello.post_greeting
      responses:
        200:
          description: greeting response
          content:
            text/plain:
              schema:
                type: string
                example: "hello dave!"
      parameters:
        - name: name
          in: path
          description: Name of the person to greet.
          required: true
          schema:
            type: string
            example: "dave"

components:
  securitySchemes:
    openId:
      type: openIdConnect
      openIdConnectUrl: http://127.0.0.1:8080/.well-known/openid-configuration

# Global security
security:
  - openId:
      - admin

curl http://127.0.0.1:9090/v1.0/greeting/wim --request POST

produces: hello wim

hjacobs commented 6 years ago

I think OpenID support is not implemented in Connexion, feel free to propose an implementation/PR (?).

dtkav commented 6 years ago

Yeah, sorry @WimDH I haven't had a chance to fully understand OpenID Connect and implement it. I've been trying to focus on getting the OpenAPI 3 support released with feature parity to Swagger 2, and then after that's released I'm happy to start adding features like this. This is definitely high on the list.

cziebuhr commented 6 years ago

You can still use oauth2 and parse the JWT yourself in x-tokenInfoFunc. Currently there's no programmatic way to access the current token from the authorization header (apart from parsing it again). Maybe I could add that to #686. Edit: Forget the second part, it's too late in the evening.

styk-tv commented 5 years ago

@hjacobs @dtkav @cziebuhr from what I understand:

One of .well-known/openid-configuration-listed endpoints is called certs (jwks_uri). It carries a list of dictionaries that are compliant with JWK (Json Web Key RFC 7517). In my Keycloak there is only one and it carries enough info to reconstruct a public key that is required to verify a signature of a JWT token.

in python RSAAlgorithm.from_jwk(keys[0]) where RSAAlgorithm comes from jwt package and keys is a direct output of certs endpoint.

Once signature on token is verified to be coming from the .well-known server, there are usually other checks like audience, expiry and so on.

As an an example unrelated directly to openapi specification i will list below kubernetes spec to demonstrate the difference in groups handling. It is fascinating to observe details of implementation of this single file over the last two years and the oidc setup being reduced to below:

spec:
  kubeAPIServer:
    oidcIssuerURL: https://your-oidc-provider.svc.cluster.local
    oidcClientID: kubernetes
    oidcUsernameClaim: email
    oidcGroupsClaim: groups  

Then in our JWT token:

screenshot 2018-12-24 at 06 54 19

might then very easily translate to in openapi.yaml:

paths:
  /pets/{petId}:
    get:
      summary: Get a pet by ID
      security:
        - openId:
          - api-user

Reason I'm listing this is I believe it is important to observe implementation that cares where the GroupClaims are coming from. As you are crafting the token, groups can be placed in different locations. I use groups, but as you are defining a mapping it could be any name. I have not seen such placeholder in the OpenApi3 Discovery specification. I would kindly ask you consider this during implementation.

So (imho) OpenIDConnect (OIDC) should care not directly about .well-known endpoint which is global to the oidcIssuer but rather on these 4 elements that are required to determine WHO against the OpenAPI security(openId) WHAT:

  1. oidcIssuerURL: (server + realm) from which the .well-known endpoints can be derived (usually by affixing .well-known/openid-configuration)
  2. oidcClientID: there might be one but as much as hundreds of clients (consumers) of the oidc details in a single realm. Each could have different flows of authorization or mappings (what data is in the token)
  3. oidcUsernameClaim: what field is defines the unique user identifier
  4. oidcGroupsClaim: what field holds the list of groups that user belongs to (based on this we can grant permissions to different api endpoints) could be as easy as pets_read, pets_write, admin or as complex as required to handle enterprise-level ldap-provided group membership mappings that span across hundreds of endpoints.

In Summary: OpenID Connect Discover (oidc) is very close from being fully realized in python for OpenApi. Personally I have both beautiful dreams and nightmares about this section for a long time. I think for all of us, getting to a point where you can use abstracted system like Keycloak, Auth0, Google, Cognito ... with or without federated LDAP that admit control to selected endpoints based on token's self-contained details is very long awaited.

rfanjul commented 5 years ago

Hello I am just curious if there was an improvement in this issue. It is something I would like to use

julien10 commented 5 years ago

Yep, same for me, are there any news ?

gbmarc1 commented 4 years ago

Still no news on this issue?

sindre-nistad commented 4 years ago

This feature would be much appreciated.

rhernaus commented 3 years ago

I'm curious if there is any news on this issue. I would really like to use this.

georgms commented 3 years ago

+1

sknopp commented 2 years ago

+1

dmarkey commented 2 years ago

This would be great, oidc is becoming de-facto.

dmarkey commented 2 years ago

From what I can tell, it could be as simple as this: https://github.com/dmarkey/connexion/pull/1/files

But leaves it up to the application to do the JWT validation (like it would for ordinary OAuth2 tokens)