travisghansen / external-auth-server

easy auth for reverse proxies
MIT License
330 stars 44 forks source link

GitHub oauth #3

Closed runningman84 closed 5 years ago

runningman84 commented 5 years ago

Do you really need a full openid provider or would a GitHub oauth application also work?

travisghansen commented 5 years ago

I'm very close to landing server-side token support. I dreamed up a structure I really like that I think will be flexible and sane. I'm guessing I'll have it landed in the next branch before mid week as an FYI.

Guessing 0.2.0 will land sometime the week following with 3 primary features:

travisghansen commented 5 years ago

Just landed server-side tokens among other things. See CONFIG_TOKENS.md for an idea. Doc is still sparse but may be enough to get you going.

travisghansen commented 5 years ago

Anything else you need on this issue?

runningman84 commented 5 years ago

@travisghansen I got this error while using your github org example:

{"message":"starting verify pipeline","level":"info","service":"external-auth-server"}
{"service":"external-auth-server","level":"info","message":"starting verify for plugin: oauth2"}
{"service":"external-auth-server","level":"warn","message":"failed assertion: {\"query_engine\":\"jp\",\"query\":\"$.organizations[*].id\",\"rule\":{\"method\":\"contains\",\"value\":12345678}} against value: []"}

My config looks like this:

let config_token = {
  /**
   * future feature: allow blocking certain token IDs
   */
  //jti: <some known value>

  /**
   * using the same aud for multiple tokens allows sso for all services sharing the aud
   */
  //aud: "some application id", //should be unique to prevent cookie/session hijacking, defaults to a hash unique to the whole config
  eas: {
    // list of plugin definitions, refer to PLUGINS.md for details
    plugins: [
      {
        type: "oauth2",
        issuer: {
          authorization_endpoint: "https://github.com/login/oauth/authorize",
          token_endpoint: "https://github.com/login/oauth/access_token"
        },
        client: {
          client_id: "aaaaaaaaaaaaaaa",
          client_secret: "bbbbbbbbbbbbbbbbbbbbbbbbb"
        },
        scopes: ["user"],
        /**
         * static redirect URI
         * if your oauth provider does not support wildcards place the URL configured in the provider (that will return to this proper service) here
         */
        redirect_uri: "https://eas.example.com/oauth/callback",
        features: {
          /**
           * if false cookies will be 'session' cookies
           * if true and cookies expire will expire with tokens
           */
          cookie_expiry: false,

          userinfo_expiry: 86400, // 24 hours

          /**
           * sessions become a floating window *if* tokens are being refreshed or userinfo being refreshed
           */
          session_expiry: 604800, // 7 days

          /**
           * if session_expiry is a number and this is set then sessions become a 'floating window'
           * if activity is triggered in this amount of time *before* preceeding the end of the
           * session then the expiration time is extended + session_expiry
           */
          session_expiry_refresh_window: 86400, // 24 hours

          /**
           * will re-use the same id (ie: same cookie) for a particular client if a session has expired
           */
          session_retain_id: true,

          /**
           * if the access token is expired and a refresh token is available, refresh
           */
          refresh_access_token: true,

          /**
           * fetch userinfo and include as X-Userinfo header to backing service
           */
          fetch_userinfo: true,

          userinfo: {
            provider: "github",
            config: {
              fetch_teams: true,
              fetch_organizations: true,
              fetch_emails: true
            }
          },

          /**
           * which token (if any) to send back to the proxy as the Authorization Bearer value
           * note the proxy must allow the token to be passed to the backend if desired
           *
           * possible values are access_token, or refresh_token
           */
          //authorization_token: "access_token"
        },
        assertions: {
          /**
           * assert the token(s) has not expired
           */
          exp: true,           
          userinfo: [
            {
              query_engine: "jp",
              query: "$.organizations[*].id",
              rule: {
                method: "contains",
                value: 12345678
                //negate: true,
                //case_insensitive: true
              }
            }
          ]
        },
        cookie: {
          name: "_eas_github_session_", //default is _oeas_oauth_session
          domain: "dev.example.com" //defaults to request domain, could do sso with more generic domain
          //path: "/",
        }
      }
    ]
  }
};

Do you have any idea how to fix this issue? (12345678 is our redacted github org id)

runningman84 commented 5 years ago

I spend some time debugging this issue. It looks like the organizations is empty for my users. Funny enough my users have an team array which also contain an organisation id. This is from the debug logs:

{
    "iat": 1563454644,
    "data": {
        "login": "testuser",
        "id": 12345678,
        "node_id": "MDQ6VXNlcjE2OTkxMjg=",
        "avatar_url": "https://avatars2.githubusercontent.com/u/12345678?v=4",
        "gravatar_id": "",
        "url": "https://api.github.com/users/testuser",
        "html_url": "https://github.com/testuser",
        "followers_url": "https://api.github.com/users/testuser/followers",
        "following_url": "https://api.github.com/users/testuser/following{/other_user}",
        "gists_url": "https://api.github.com/users/testuser/gists{/gist_id}",
        "starred_url": "https://api.github.com/users/testuser/starred{/owner}{/repo}",
        "subscriptions_url": "https://api.github.com/users/testuser/subscriptions",
        "organizations_url": "https://api.github.com/users/testuser/orgs",
        "repos_url": "https://api.github.com/users/testuser/repos",
        "events_url": "https://api.github.com/users/testuser/events{/privacy}",
        "received_events_url": "https://api.github.com/users/testuser/received_events",
        "type": "User",
        "site_admin": false,
        "name": "xxx yyy",
        "company": null,
        "blog": "",
        "location": "Germany",
        "email": null,
        "hireable": null,
        "bio": null,
        "public_repos": 48,
        "public_gists": 14,
        "followers": 12,
        "following": 6,
        "created_at": "2012-05-02T14:14:03Z",
        "updated_at": "2019-05-29T20:47:04Z",
        "private_gists": 1,
        "total_private_repos": 4,
        "owned_private_repos": 4,
        "disk_usage": 2425,
        "collaborators": 0,
        "two_factor_authentication": true,
        "plan": {
            "name": "free",
            "space": 976562499,
            "collaborators": 0,
            "private_repos": 10000
        },
        "organizations": [],
        "teams": [
            {
                "name": "example-Bootcamp",
                "id": 423425345,
                "node_id": "MDQ6VGVhbTIxNjcxNTU=",
                "slug": "example-bootcamp",
                "description": "",
                "privacy": "closed",
                "url": "https://api.github.com/teams/423425345",
                "html_url": "https://github.com/orgs/example/teams/example-bootcamp",
                "members_url": "https://api.github.com/teams/423425345/members{/member}",
                "repositories_url": "https://api.github.com/teams/423425345/repos",
                "permission": "pull",
                "created_at": "2016-10-24T08:54:01Z",
                "updated_at": "2016-10-24T08:54:01Z",
                "members_count": 11,
                "repos_count": 1,
                "organization": {
                    "login": "example",
                    "id": 12345678,
travisghansen commented 5 years ago

Interesting, I don't know enough about the GitHub API to say one way or another but glad you got it worked out! If you need further help I can dig a little deeper just reopen and let me know.