Commit Graph

69 Commits

Author SHA1 Message Date
Michael Gilliland
e4c2ea72d2
Expose onDispatchError and generic error message (#150)
* Expose `onDispatchError` and generic `OtherDispatchError`

* Update changelog and version

* Restyled by prettier-markdown (#151)

Co-authored-by: Restyled.io <commits@restyled.io>

Co-authored-by: restyled-io[bot] <32688539+restyled-io[bot]@users.noreply.github.com>
Co-authored-by: Restyled.io <commits@restyled.io>
2021-04-09 11:46:24 -04:00
Joseph Morag
c4d6a5d28d Expose custom widgets for google oauth 2021-03-08 09:40:26 -05:00
Restyled.io
e0bcb43207 Restyled by stylish-haskell 2021-03-05 11:41:29 -05:00
patrick brisbin
62dff1dd18 Tighten up callback expression 2021-03-05 11:41:29 -05:00
patrick brisbin
9dafb18923 Use (<$) 2021-03-05 11:41:29 -05:00
patrick brisbin
80552b399c Clean up maybe 2021-03-05 11:41:29 -05:00
patrick brisbin
0f09dd1d05 In-line errLeft 2021-03-05 11:41:29 -05:00
patrick brisbin
65694e10d7 In-line tryFetchCreds 2021-03-05 11:41:29 -05:00
patrick brisbin
b71ae8f60d Check for ErrorResponse before CSRF
It's possible there's an error that explains why the state token isn't
as expected. It should be fine to report those details before verifying
CSRF.
2021-03-05 11:41:29 -05:00
patrick brisbin
ab17f214eb Consolidate all errors, use onErrorHtml
Prior to this commit, some errors would be thrown (missing parameter,
invalid state, incorrect approot) while others would be handled via the
set-message-redirect approach (handshake failure, fetch-token failure,
etc).

This commit consolidates all of these cases into a single DispatchError
type, and then uses MonadError (concretely ExceptT) to capture them all
and handle them in one place ourselves.

It then updates that handling to:

- Use onErrorHtml

  onErrorHtml will, by default, set-message-redirect. That make this
  behavior neutral for users running defaults. For users that have
  customized this, it will be an improvement that all our error cases
  now respect it.

- Provided a JSON representation of errors
- Attach a random correlation identifier

The last two were just nice-to-haves that were cheap to add once the
code was in this state.

Note that the use of MonadError requires a potentially "bad" orphan
MonadUnliftIO instance for ExceptT, but I'd like to see that instance
become a reality and think it needs some real-world experimentation to
get there, so here I am.
2021-03-05 11:41:29 -05:00
patrick brisbin
a09528a07f Exclude + from state tokens
When the state token is sent to an OAuth2 provider, it undergoes
%-encoding as a URL parameter. Presumably, the OAuth2 provider decodes
it as part of handling things (because it would take work to prevent
their own web frameworks from doing so), and then re-%-encodes it coming
back to us again as a callback parameter.

For us, and all existing providers, + is not a %-encoded character, so
it's sent as-is and sent back as-is. So far so good.

ClassLink, though, chooses to decode + to space. I'm not aware of the
actual spec or if this is a reasonable thing to do, but they do. This
results in them sending %20 back to us, which doesn't match and we fail.

We can't predict or prescribe what providers do in this area, so our
options are:

- Look for a match in our Session as-is OR with spaces replaced by +

  This is harder than it sounds: a token could contain +'s or spaces,
  and we'd be getting back only spaces. To succeed, we'd actually have
  to check every permutation of space/+ substitution.

- Filter + from our tokens

  The only downside is we may generate slightly fewer than 30
  characters, and so produce slightly less secure tokens.

  I chose this option.

- Generate tokens without + to begin with

  This would be ideal, but I'm just not familiar enough with
  Crypto.Random. I would happily accept a PR to use this option.
2021-01-14 10:21:46 -05:00
patrick brisbin
20ff7feaac Add ClassLink plugin 2021-01-14 10:21:46 -05:00
patrick brisbin
bbda0d2f47 Support injecting fetchAccessToken
hoauth2's fetchAccessToken provides credentials in the Authorization
header, while fetchAccessToken2 provides them in that header but also
the POST body.

It was discovered that some providers only support one or the other, so
using fetchAccessToken2 would be preferred since it should work with
either. This happened in #129.

However, we discovered at least one provider (Okta) that actively
rejects requests unless they're supplying credentials in exactly one
place:

    Cannot supply multiple client credentials. Use one of the following:
    credentials in the Authorization header, credentials in the post
    body, or a client_assertion in the post body."

This patch reverts back to fetchAccessToken, but makes it possible to
for client to use fetchAccessToken2 if necessary via alternative
functions.
2020-12-10 15:20:31 -05:00
patrick brisbin
1f6d08dc8b Brittany 2020-12-10 15:20:31 -05:00
patrick brisbin
ebc12e49ff Lint ErrorResponse 2020-08-24 10:49:14 -04:00
patrick brisbin
cbe4aed1c8 Brittany ErrorResponse 2020-08-24 10:49:14 -04:00
patrick brisbin
28d2113674 Update to latest GHC, Stackage resolver, hoauth2
- Update to ghc-8.8 / lts-16.0
- Update to hoauth2 >= 1.11.0

  - authGetBS has pre-encoded errors a v1.9
  - oauthClientSecret is Maybe at v1.11

- Tweak non-default Resolvers as required
2020-08-24 10:49:14 -04:00
patrick brisbin
c939633a96 Reformat with Brittany 2020-08-24 10:49:14 -04:00
patrick brisbin
cd3875b797 Strengthen random state token generation
Previously:

- System.Random, which seeds from system time (possible attack)
- 30 characters, a-z (low entropy)

Now:

- Crypto.Random, accepted as "cryptographically secure"
- 64 random bytes, Base64-encoded

cryptonite was already a transitive dependency, so there is really no
downside to this.

Fixes #132.
2020-08-20 11:38:20 -04:00
patrick brisbin
60c0f68d5a
Cleanup WordPress plugin
- Explicit exports
- Fixup Haddock formatting
- Brittany & Stylish
- CHANGELOG attribution
2020-08-19 11:17:22 -04:00
nbloomf
13b84a8724 Add WordPress.com as an auth provider
Documentation at https://developer.wordpress.com/docs/wpcc/
2020-08-19 10:57:14 -04:00
nbloomf
1576af3fa5 Replace call to fetchAccessToken with fetchAccessToken2
This comment comes from hoauth2:

-- OAuth2 spec allows `client_id` and `client_secret` to
-- either be sent in the header (as basic authentication)
-- OR as form/url params.
-- The OAuth server can choose to implement only one, or both.
-- Unfortunately, there is no way for the OAuth client (i.e. this library) to
-- know which method to use. Please take a look at the documentation of the
-- service that you are integrating with and either use `fetchAccessToken` or `fetchAccessToken2`

`fetchAccessToken2` is a drop-in replacement for `fetchAccessToken` that just adds `client_id` and `client_secret` to the body as form parameters, as permitted by [RFC 6749](https://tools.ietf.org/html/rfc6749#section-2.3.1). Some authorization server implementations only accept client credentials in this form.
2020-07-08 10:15:40 -04:00
patrick brisbin
b998e03067 Brittany 2019-12-03 20:27:15 -05:00
patrick brisbin
48277d9b8e Compile on nightly/ghc-8.8 2019-12-03 20:27:15 -05:00
patrick brisbin
8436c8ff27 Don't handle unexpected errors with Unknown
This was lazy and resulted in a confusing error experience where a
JSONDecodingError fetching credentials appeared as an Unknown OAuth2
ErrorResponse, making it appear like the OAuth2 provider was indicating
this error to us, instead of it being a simple incorrect parser in our
own code.

ErrorResponse is specifically meant to parse error parameters sent to us
by the OAuth2 provider. They may be user-actionable and can be safely
displayed. This is a very narrow use-case. The Unknown constructor is
required for us to be exhaustive on our string error names, but it
should not be hijacked to store our own errors.

This commit separates and documents the two error scenarios.
2019-08-29 17:21:28 -04:00
Chris Beavers
208f497a5a Add AzureAD provider 2019-03-09 09:14:50 -05:00
patrick brisbin
b8befc4811
Remove deprecated Github module 2018-11-24 14:11:44 -05:00
patrick brisbin
1411bb5858 Implement different exceptions for different cases
I had hoped to get away from this entirely, to an Either-based
interface, but that seems to be stalling as an initiative. So in the
meantime, let's at least make our exceptions more meaningful.
2018-09-19 07:55:38 -04:00
patrick brisbin
e3c61789ba Ensure we rescue our exceptions too
For some reason, I thought tryIO would catch our own exception is we
threw them via throwIO, but that's incorrect. Our own exceptions are not
IOExceptions, so they squeak by. This fixes that.
2018-09-18 17:25:00 -04:00
patrick brisbin
dc033e1331 Move Exception to its own module
This will avoid cycles later.
2018-09-18 17:25:00 -04:00
patrick brisbin
37343fa533 Redirect on OAuth2 errors, not permissionDenied 2018-09-18 17:25:00 -04:00
patrick brisbin
92beb4b4b4 Brittany 2018-09-18 17:25:00 -04:00
patrick brisbin
6d0077a534 Deprecate improperly-cased Github module 2018-07-30 11:46:02 -04:00
patrick brisbin
c86fa6de13 Create properly-named GitHub module 2018-07-30 11:46:02 -04:00
patrick brisbin
44c05d7a2d Store refreshToken in credsExtra, if available 2018-07-30 09:10:37 -04:00
patrick brisbin
d9eeb787d6 Make comments clearer 2018-07-30 09:10:37 -04:00
patrick brisbin
dacc71f008 Add GitLab support 2018-07-29 09:45:00 -04:00
patrick brisbin
98ef5f9aae Update LTS and dependencies
- Latest LTS-11.5
- Allow hoauth2-1.7, needs to be extra-dep though
- Support *and require* yesod-1.6

  This required:

  - Less lifts
  - HandlerFor, WidgetFor, etc
  - Lost MonadThrow, but can use MonadIO instead
2018-04-21 10:49:05 -04:00
patrick brisbin
dddfbd9f3c Look for and handle OAuth error responses
Closes #106.
2018-03-27 18:40:26 -04:00
patrick brisbin
aa9736b80e Extract errInvalidOAuth 2018-03-27 18:40:26 -04:00
patrick brisbin
a91f85ff38
Improve error message for invalid Approots
Closes #87
2018-02-13 09:10:04 -05:00
patrick brisbin
5096ca04aa Fix Google Plugin
Scopes need to be separated by space, not +.
2018-02-13 08:59:01 -05:00
patrick brisbin
72c64102b0 Fix BattleNet interface
- Incorrect indentation
- We should always accept Id/Secret last
- The function is oauth... not oAuth...

Because of the mis-naming, at least we could fix the argument-order in a
backwards-compatible way, deprecating the old function/interface.
2018-02-13 08:59:01 -05:00
patrick brisbin
ef38c5c49d Docs tweaks 2018-02-12 09:10:34 -08:00
patrick brisbin
93258d4468 Make extras accessors safer
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.
2018-02-12 09:10:34 -08:00
patrick brisbin
a2a49a2c57 Set the ByteString body at userResponse
- It may not be JSON (thought it always is now)
- The JSON suffix should be used only when it is (such as in
  getUserResponseJSON)
2018-02-12 09:10:34 -08:00
patrick brisbin
41eda086a1 Fixup Google documentation 2018-02-12 09:10:34 -08:00
patrick brisbin
794fbbf7e8 Add functions for reading credsExtra 2018-02-12 09:10:34 -08:00
patrick brisbin
32740037e3 Remove unused functions, reduce Prelude interface 2018-02-12 09:10:34 -08:00
patrick brisbin
c586c72df7 Remove extra fields from Upcase 2018-02-12 09:10:34 -08:00