Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stop returning extra information in GitHub result #100

Merged
merged 19 commits into from
Feb 12, 2018
Merged

Conversation

pbrisbin
Copy link
Member

See #71.

New credsExtra keys:

  • accessToken: so you can make your own follow-up requests
  • userResponseJSON: so you can get more information out of the request
    we already made (you just have to parse it yourself)

Removed keys:

  • access_token: renamed to accessToken
  • avatar_url: can be re-parsed
  • email: requires your own request to /emails
  • login: can be re-parsed from userResponseJSON
  • location: can be re-parsed, was not always present
  • name: can be re-parse, was not not always present
  • public_email: can be re-parsed, was not not always present

I'll start going provider by provider now.

See #71.

New `credsExtra` keys:

- `accessToken`: so you can make your own follow-up requests
- `userResponseJSON`: so you can get more information out of the request
  we already made (you just have to parse it yourself)

Removed keys:

- `access_token`: renamed to `accessToken`
- `avatar_url`: can be re-parsed
- `email`: requires your own request to `/emails`
- `login`: can be re-parsed from `userResponseJSON`
- `location`: can be re-parsed, was not always present
- `name`: can be re-parse, was not not always present
- `public_email`: can be re-parsed, was not not always present

Also re-orders arguments between default and scoped to allow better
partial application -- taking advantage of API breakage already.
New keys:

- accessToken
- userResponseJSON

Removed keys:

- battleTag
New keys:

- accessToken
- userResponseJSON

Removed keys:

- email
- login
- avatar_url
- access_token
- name
- location
Removed keys:

- charName
- charId
- tokenType
- expires

All can be recovered by re-parsing userResponseJSON.
Also removes the ability to parse a custom identifier. See the module
documentation for a workaround.
@pbrisbin
Copy link
Member Author

pbrisbin commented Jan 28, 2018

I decided to store the raw response at userResponse (not userResponseJSON), since it doesn't have to be JSON. We're providing our own lookup functions, so getUserResponse will return ByteString and getUserResponseJSON will return it parsed to FromJSON a, and may fail if misused.

Also, I'm starting to see a slightly better Provider type come together:

data Provider = Provider
  { pName :: ProviderName
  , pToOAuth2 :: ClientId -> ClientSecret -> OAuth2
  , pFetchUserResponse :: Manager -> OAuth2Token -> Either String ByteString
  , pParseCredsIdent :: ByteString -> Either String Text
  }

something :: YesodAuth m => Provider -> ClientId -> ClientSecret -> AuthPlugin m
something Provider{..} clientId clientSecret =
  authOAuth2 pName (pToOAuth2 clientId clientSecret) $ \manager token -> do
    -- Assumes we adjust authOAuth2 to use Either, not exceptions
    userResponse <- pFetchUserResponse manager token
    userId <- pParseCredsIdent userResponse

    pure Creds
      { credsPlugin = pName
      , credsIdent = userId
      , credsExtra = setExtra token userResponse
      }

I think I'll branch from this and try that out, as a replacement for #92

@pbrisbin pbrisbin mentioned this pull request Feb 5, 2018
4 tasks
--
getAccessToken :: Creds m -> AccessToken
getAccessToken = AccessToken
. fromJustNote "yesod-auth-oauth2 bug: credsExtra without accessToken"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bummer that we have to use fromJust here. Is this because Yesod.Auth.Creds doesn't have a type parameter, so we have to use stringly typed data for the "extra" bits? Would it be worth trying to change this in Yesod.Auth?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, this is not necessarily a bug, right? If somebody authenticates with username/password and then calls getAccessToken with those creds, that will compile and crash?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be worth trying to change this in Yesod.Auth?

I'm not really sure that would work. Even if it were Creds e m, for some extras type e, that e couldn't be plugin-specific because it must be the same across all plugins in use. Maybe I'm missing something clever though.

Also, this is not necessarily a bug, right? If somebody authenticates with username/password and then...

You're absolutely right; great catch. I think I lean towards making this Maybe now. I thought there was strong guarantees a value would be present, but non-oauth2-plugins is way too likely.

@jferris
Copy link
Contributor

jferris commented Feb 7, 2018

Nice to see some cleanup and simplification here.

Even though it's "guaranteed" that values will be present because we set
them, nothing stops end-users from using these functions on Creds values
created by other plugins! Since that seems common, it would be
irresponsible of us to remain so unsafe.
@owickstrom
Copy link

@pbrisbin Great stuff, really looking forward to this change!

@@ -51,3 +61,22 @@ authOAuth2Widget widget name oauth getCreds =
AuthPlugin name (dispatchAuthRequest name oauth getCreds) login
where
login tm = [whamlet|<a href=@{tm $ oauth2Url name}>^{widget}|]

-- | Read from the values set via @'setExtra'@
getAccessToken :: Creds m -> Maybe AccessToken
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be more convenient for users to use Either String for all the get* functions. For example, that would let users combine them monadically without writing their own conversions between Either String and Maybe.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know that I follow your reasoning: I think we can't really predict what Monad the user will want to be in, so I don't know that Either would fit any better at call-sites than Maybe (they'll almost certainly be in Handler 99% of the time)... But I can get behind Either for this because it retains information users could choose to silence when in Maybe (e.g. hush), vs the current way where the user would have to invent information when in Either (e.g. note) -- so 👍

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, on second thought I'm not sure. Having these return Either feels like if Map.lookup returned either: that'd be silly because there's only one way it can fail.

I think I'm going to keep this for now.

@pbrisbin pbrisbin merged commit ef38c5c into master Feb 12, 2018
@pbrisbin pbrisbin deleted the pb/fetch-creds branch February 12, 2018 17:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants