greenpau / caddy-security

🔐 Authentication, Authorization, and Accounting (AAA) App and Plugin for Caddy v2. 💎 Implements Form-Based, Basic, Local, LDAP, OpenID Connect, OAuth 2.0 (Github, Google, Facebook, Okta, etc.), SAML Authentication. MFA/2FA with App Authenticators and Yubico. 💎 Authorization with JWT/PASETO tokens. 🔐
https://authcrunch.com/
Apache License 2.0
1.45k stars 71 forks source link

question: access rest api behind auth #103

Open axi92 opened 2 years ago

axi92 commented 2 years ago

A clear and concise description of what you want to accomplish.

I got an application with an rest endpoint. I can login through the ui and access the app. But I have not managed to do this via curl. We use keycloak as the oauth plugin. With keycloak there are different tokens id and access token and I have not managed to get the right calls to get through the auth portal.

greenpau commented 2 years ago

@axi92 , please provide your config and specify which route handles the rest endpoint.

axi92 commented 2 years ago

The endpoint would be https://releases.evva.link/sfw-releases/

And the config:

{
    debug

    order authenticate before respond
    order authorize before basicauth

    security {
        oauth identity provider keycloak {
            driver generic
            realm keycloak
            client_id {env.KEYCLOAK_CLIENT_ID}
            client_secret {env.KEYCLOAK_CLIENT_SECRET}
            scopes openid email profile
            metadata_url https://keycloak.evva.com/auth/realms/master/.well-known/openid-configuration
        }

        authentication portal myportal {
            crypto default token lifetime 3600
            crypto key sign-verify {env.JWT_SHARED_KEY}
            enable identity provider keycloak
            cookie domain evva.link
            ui {
                links {
                    "releases" https://releases.evva.link icon "las la-link"
                    "My Identity" "/whoami" icon "las la-user"
                }
            }
            transform user {
                match origin keycloak
                action add role authp/user
            }
        }

        authorization policy mypolicy {
            set auth url https://auth.evva.link/
            allow roles authp/admin authp/user
            crypto key verify {env.JWT_SHARED_KEY}
        }
    }
}

releases.evva.link {
    authorize with mypolicy
    reverse_proxy http://10.64.192.146:8888
    import letls
}
greenpau commented 2 years ago

@axi92 , when you curl to your API, you would need providing the token acquired via authentication portal. What is the curl command you are using?

axi92 commented 2 years ago

Yes the problem is how do I get the token from the auth portal? I used this

export TKN=$(curl -X POST 'https://keycloak.evva.com/auth/realms/master/protocol/openid-connect/token' \
 -H "Content-Type: application/x-www-form-urlencoded" \
 -d 'username=USERNAME' \
 -d 'password=PASSWORD' \
 -d 'grant_type=password' \
 -d 'client_id=caddy-security-portal' | jq -r '.access_token')
greenpau commented 2 years ago

Yes the problem is how do I get the token from the auth portal?

@axi92 , you do it like this https://authp.github.io/docs/authenticate/misc#authenticate

greenpau commented 2 years ago

@axi92 , please search the docs on how to enable accepting bearer token.

Once you authenticate to the portal and get the token, you pass that token in “ -H 'Authorization: Bearer: eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2Mzg3MzgyMjEsImp0aSI6IlN6d2JiOXI5eG5NeVlHUE5IbGZHeklQVlc5VHVLY1VlcndMbmNHR1BtIiwiaWF0IjoxNjM4NzM0NjIxLCJpc3MiOiJodHRwczovL2F1dGgubXlmaW9zZ2F0ZXdheS5jb206ODQ0My9sb2dpbiIsIm5iZiI6MTYzODczNDU2MTAwMCwic3ViIjoid2ViYWRtaW4iLCJlbWFpbCI6IndlYmFkbWluQGxvY2FsZG9tYWluLmxvY2FsIiwicm9sZXMiOlsiYXV0aHAvYWRtaW4iLCJhdXRocC91c2VyIl0sIm9yaWdpbiI6ImxvY2FsIiwiYWRkciI6IjEwLjAuMi4yIn0.QuSld2zKYtQX5gPIUlg7glRb7GXuieXm7ALxBTRd2dxCK4T-cZN-2KiK376Z1sxSFf3P3PA-ycrcazjdU5XETQ' “ header when making calls to your API.

greenpau commented 2 years ago

@axi92 , wait … the things I mentioned would not work with OAuth. Let me think and I will let you know how to go about it.

greenpau commented 2 years ago

@axi92 , 😄 I might know how to do it! 😆 ...

So ... I decided adding a feature that would take the id_token or access_token received from OAuth2.0 provider (e.g. Keycloak) and create a new cookie (AUTHP_IDP_ACCESS_TOKEN or AUTHP_IDP_ID_TOKEN) which would hold the tokens.

The new cookie will be next to the existing access_token and AUTHP_SESSION_ID issued by the portal.

image


Then, there are 2 options to handle this.

  1. Create /whoami/id_token which would return the id_token. You apps can then use the extracted token when accessing API
  2. Configured you apps to access AUTHP_IDP_ID_TOKEN

Does the above make sense?

greenpau commented 2 years ago

@axi92 , I am ready to get back to this. The gist is that I will be taking id_token sent by OAuth provider and injecting it into a cookie accessible only by the auth portal. Please see https://github.com/authp/authp.github.io/issues/28

Then, I will be able to retrieve it from SPA using the following URL parameters, e.g. https://auth.myfiosgateway.com:8443/whoami?format=json&id_token=true. The reply would contain JSON document with id_token field populated with the token received from OAuth provider.

Tested it with AWS Cognito and it works. My guess is that it would work with keycloak too.

lucasbaile commented 2 years ago

Sorry to revive this topic, but I'm in a similar situation here, and can't seem to understand exacly how to use the feature described in https://github.com/authp/authp.github.io/issues/28

The briefly elaborate what I want to do:

My config is pretty basic, as described in the docs:

{
    order authenticate before respond
    order authorize before basicauth

    security {
        oauth identity provider google {
            realm google
            driver google
            client_id XX
            client_secret XX
            scopes openid email profile
            enable id_token cookie
        }

        authentication portal myportal-xx.com {
            crypto default token lifetime 3600
            crypto key sign-verify {env.JWT_SHARED_KEY}
            enable identity provider google
            cookie domain xx.com

            transform user {
                match realm google
                action add role authp/user
            }

            transform user {
                match realm google
                match email sysadmin@xx.com
                action add role authp/admin
            }
        }

        authorization policy mypolicy-xx.com {
            set auth url https://auth.xx.com/oauth2/google/authorization-code-callback
            crypto key verify {env.JWT_SHARED_KEY}
            allow roles authp/admin authp/user
            validate bearer header
            inject headers with claims
        }

}

auth.xx.com {
    authenticate with myportal-xx.com
}

xx.com {
    authorize with mypolicy-xx.com

    file_server * {
        root /web-data/
    }
    log {
        format console
    }
}

The auth is working fine, but now I would like to programmatically find a way to curl some pages behind this auth. for example:

curl -X GET -H 'Accept: application/json' -H 'Content-Type: application/json' -H "Authorization: Bearer $TOKEN" https://xx.com/overview.json

I assumed I could use use the access token generated via gcloud auth print-access-token for this, but as you described above, I can't use this procedure with OAuth, and can't seem to understand how should I adjust my curl command to get my access_token from google to work with this feature in https://github.com/authp/authp.github.io/issues/28. Can you help me out?

greenpau commented 2 years ago

I assumed I could use use the access token generated via gcloud auth print-access-token for this, but as you described above

@lucasbaile , at the moment this feature only works with local identity store.

curl -X GET -H 'Accept: application/json' -H 'Content-Type: application/json' -H "Authorization: Bearer $TOKEN" https://xx.com/overview.json

The $TOKEN should be the token issued by auth portal. It should work.

greenpau commented 2 years ago

@lucasbaile , also, you issue is slightly different from the one originally asked here. It is best if you open a new issue.

lucasbaile commented 2 years ago

I understand, sorry for the confusion!

Just opened a new issue on that matter 👍

mgmorcos commented 7 months ago

hi the link to the issue below is currently broken. is there another link for the same information? thank you for this useful project.

https://github.com/authp/authp.github.io/issues/28

greenpau commented 7 months ago

@mgmorcos , look for the issue in authcrunch/authcrunc.github.io repo. I recently migrated it.