no issue
- it can happen that concurrent requests try to renew access tokens with the same refresh token
- in this case it could happen that you received a token deletion error
- add propert locking
- ensure we don't run into deadlocks
- manual testing with async.times for parallel requests (was able to reproduce the error)
refs #8613, refs #9228
- if you send a request to /authentication/token with `grant_type:password` and a Bearer token, Ghost was not able to handle this combination
- because it skipped the client authentication, see https://github.com/TryGhost/Ghost/blob/1.17.0/core/server/auth/authenticate.js#L13
- and OAuth detects the `grant_type: password` and jumps in the target implementation
- the target implementation for password authentication **again** tried to fetch the client and failed, because it relied on the previous client authentication
- see https://github.com/TryGhost/Ghost/blob/1.17.0/core/server/auth/oauth.js#L40 (client.slug is undefined if client authentication is skipped)
- ^ so this is the bug
- we **can** skip client authentication for requests to the API to fetch data for example e.g. GET /posts (including Bearer)
- so when is a client authentication required?
- RFC (https://tools.ietf.org/html/rfc6749#page-38) differentiates between confidential and public clients, Ghost has no implementation for this at the moment
- so in theory, public clients don't have to be authenticated, only if the credentials are included
- to not invent a breaking change, i decided to only make the client authentication required for password authentication
- we could change this in Ghost 2.0
I have removed the extra client request to the database for the password authentication, this is not needed. We already do client password authentication [here](https://github.com/TryGhost/Ghost/blob/1.17.0/core/server/auth/auth-strategies.js#L19);
If a Bearer token is present and you have not send a `grant_type` (which signalises OAuth to do authentication), you can skip the client authentication.
closes#8342
- no need to add a migration, because when we'released 1.0, OAuth was never an option
- it was disabled in April, 1.0-beta was released in June
- remove all remote authentication code
no issue
- adds a ghost-backup client
- adds a client authenticated endpoint to export blog for ghost-backup client only
- allows some additional overrides during import
- allows for an import by file to override locking a user and double hashing the password
no issue
- Upgraded ghost-ignition
- Use debug from ghost-ignition everywhere in the code base
- Remove debug dependency
- Fixed random typo in Gruntfile.js
closes#8067
- this is only a bug present for remote authentication
- right now the remote service does not return the name of the user
- depends on an internal PR
- force regenerating the slug on setup
- override name for signin or invite if needed
no issue
- this is secured by client credentials
- you can only fetch the user info if the user is connected to your blog (invited, owner)
- passport ghost instance stores the client credentials in the instance, no need to pass them into
- tested on staging
refs #8111
- Ghost returns now all (active+none active) users by default
- protect login with suspended status
- test permissions and add extra protection for suspending myself
- if a user is suspended and tries to activate himself, he won't be able to proceed the login to get a new token
no issue
If the user changes the email in the remote auth service and executes a logout directly afterwards, the user would lock himself out of his blog, because the email sync happens once per hour right now.
For that case, we have to store the ghost auth id.
* 🎨 deny auto switch
no issue
- deny auth switch after the blog was setup
- setup completed depends on the status of the user right now, see comments
* Updates from comments
- re-use statuses in user model
- update error message
* ✨ ghost auth: sync email
refs #7452
- sync email changes in background (every hour right now)
- sync logged in user only!
- no sync if auth strategy password is used
- GET /users/me is triggered on every page refresh
- added TODO to support or add long polling for syncing data later
- no tests yet on purpose, as i would like to get a basic review first
* 🐩 use events
- remember sync per user
no issue
- we have to remember the auth url in Ghost
- if Ghost starts for the first time, it registers a public client in the defined auth service
- if you change the auth service, Ghost won't recognize
- if Ghost doesn't recognize, you will see a client does not exist error in Ghost Admin
no issue
- auth.init happens in background and if an error occurs, Ghost will log this error to stdout/file
- do not double create Ignition error
- update passport-ghost to handle a none response from the auth service (e.g. wrong auth url), see 123da4dd94
closes#7766, refs #7579
- ensure we are using the correct brute keys
- ensure we are using req.ip as Ghost is configured with trust proxy option
- tidy up a little
* 🎨 schema change
- simply role_id attribute
* 🎨 update invite model
- remove all methods we don't need
- ensure we remove the relation from the model
- ensure we do not allow to call withRelated
* 🎨 adapt api changes
* 🎨 adapt auth module
* 🎨 adapt tests
* 🎨 better error handling
* schema update
refs #7494, refs #7495
This PR is an extracted clean up feature of #7495.
We are using everywhere static id checks (userId === 0 or userId === 1).
This PR moves the static values into the Base model.
This makes it 1. way more readable and 2. we can change the id's in a central place.
I changed the most important occurrences - no tests are touched (yet!).
The background is: when changing from auto increment id (number) to ObjectId's (string) we still need to support id 1 and 0, because Ghost relies on these two static id's.
I would like to support using both: 0/1 as string and 0/1 as number.
1 === owner/internal
0 === external
Another important change:
User Model does not longer define the contextUser method, because i couldn't find a reason?
I looked in Git history, see 6e48275160
* 🎨 use updateClient function to update redirectUri
refs #7654
* 🎨 name instead of clientName
* 🎨 config.get('theme:title') for client name
- initial read can happen from config
* ✨ register public client: client name and description
- no update yet
- for initial client creation
- we forward title/description to Ghost Auth
- TODO: use settings-cache when merged
* ✨ store blog_uri in db
* 🎨 passport logic changes
- use updateClient instead of changeCallbackURL
- be able to update: blog title, blog description, redirectUri and blogUri
- remove retries, they get implemented in passport-ghost soon
- reorder logic a bit
* 🛠 passport-ghost 1.2.0
* 🎨 tests: extend DataGenerator createClient
- set some defaults
* 🎨 tests
- extend tests
- 👻
* ✨ run auth.init in background
- no need to block the bootstrap process
- if client can't be registered, you will see an error
- ensure Ghost-Admin renders correctly
* 🛠 passport-ghost 1.3.0
- retries
* 🎨 use client_uri in Client Schema
- adapt changes
- use blog_uri only when calling the passport-ghost instance
- Ghost uses the client_uri notation to improve readability
* ✨ read blog title/description from settings cache
* 🚨 Ghost Auth returns email instead of email_address
- adapt Ghost
no issue
- removes count from user checks model
- uses brute express brute with brute-knex adaptor to store persisted data on spam prevention
- implement brute force protection for password/token exchange, password resets and private blogging
* 🎨 rotation config
- every parameter is configureable
- increase default number of files to 100
* 🎨 ghost.log location
- example: content/logs/http___my_ghost_blog_com_ghost.log
- user can change the path to something custom by setting logging.path
* 🛠 add response-time as dependency
* 🎨 readable PrettyStream
- tidy up
- generic handling (was important to support more use cases, for example: logging.info({ anyKey: anyValue }))
- common log format
- less code 🕵🏻
* 🎨 GhostLogger cleanup
- remove setLoggers -> this function had too much of redundant code
- instead: add smart this.log function
- remove logging.request (---> GhostLogger just forwards the values, it doesn't matter if that is a request or not a request)
- make .warn .debug .info .error small and smart
* 🎨 app.js: add response time as middleware and remove logging.request
* 🎨 setStdoutStream and setFileStream
- redesign GhostLogger to add CustomLoggers very easily
----> Example CustomLogger
function CustomLogger(options) {
// Base iterates over defined transports
// EXAMPLE: ['stdout', 'elasticsearch']
Base.call(this, options);
}
util.inherits(...);
// OVERRIDE default stdout stream and your own!!!
CustomLogger.prototype.setStdoutStream = function() {}
// add a new stream
// get's called automatically when transport elasticsearch is defined
CustomLogger.prototype.setElasticsearchStream = function() {}
* 🎨 log into multiple file by default
- content/logs/domain.error.log --> contains only the errors
- content/logs/domain.log --> contains everything
- rotation for both files
* 🔥 remove logging.debug and use npm debug only
* ✨ shortcuts for mode and level
* 🎨 jshint/jscs
* 🎨 stdout as much as possible for an error
* 🎨 fix tests
* 🎨 remove req.ip from log output, remove response-time dependency
* 🎨 create middleware for logging
- added TODO to move logging middleware to ignition
* 🎨 one token endpoint
refs #7562
- delete /authentication/ghost
- Ghost-Admin will use /authentication/token for all use cases (password, refresh token and ghost.org authorization code)
- add new grant_type `authorization_code`
* 🎨 update comment description and remove spamPrevention.resetCounter
refs #4172
* 🎨 Use bodyParser only where it is needed
This is a pretty extreme optimisation, however in the interests of killing middleware/index.js it
seemed prudent to move towards not having in there that wasn't strictly necessary 😁
We should reassess how apps do this sort of thing, but it seems pretty sane to declare bodyParsing
if and only if it is necessary.
* 🎨 Move all API code to API router
* 🎨 Refactor API into an App, not just a router
- Apps have their own rendering engines, only the frontend & the admin panel need views
- The API should be JSON only, with minimal middleware
- Individual sections within the API could/should be treated as Routers
* 🎨 Flatten API middleware inclusion
- get rid of the weird middleware object
- move the api-only middleware into the middleware/api folder
refs #7116, refs #2001
- Changes the way Ghost errors are implemented to benefit from proper inheritance
- Moves all error definitions into a single file
- Changes the error constructor to take an options object, rather than needing the arguments to be passed in the correct order.
- Provides a wrapper so that any errors that haven't already been converted to GhostErrors get converted before they are displayed.
Summary of changes:
* 🐛 set NODE_ENV in config handler
* ✨ add GhostError implementation (core/server/errors.js)
- register all errors in one file
- inheritance from GhostError
- option pattern
* 🔥 remove all error files
* ✨ wrap all errors into GhostError in case of HTTP
* 🎨 adaptions
- option pattern for errors
- use GhostError when needed
* 🎨 revert debug deletion and add TODO for error id's
- 🛠 add bunyan and prettyjson, remove morgan
- ✨ add logging module
- GhostLogger class that handles setup of bunyan
- PrettyStream for stdout
- ✨ config for logging
- @TODO: testing level fatal?
- ✨ log each request via GhostLogger (express middleware)
- @TODO: add errors to output
- 🔥 remove errors.updateActiveTheme
- we can read the value from config
- 🔥 remove 15 helper functions in core/server/errors/index.js
- all these functions get replaced by modules:
1. logging
2. error middleware handling for html/json
3. error creation (which will be part of PR #7477)
- ✨ add express error handler for html/json
- one true error handler for express responses
- contains still some TODO's, but they are not high priority for first implementation/integration
- this middleware only takes responsibility of either rendering html responses or return json error responses
- 🎨 use new express error handler in middleware/index
- 404 and 500 handling
- 🎨 return error instead of error message in permissions/index.js
- the rule for error handling should be: if you call a unit, this unit should return a custom Ghost error
- 🎨 wrap serve static module
- rule: if you call a module/unit, you should always wrap this error
- it's always the same rule
- so the caller never has to worry about what comes back
- it's always a clear error instance
- in this case: we return our notfounderror if serve static does not find the resource
- this avoid having checks everywhere
- 🎨 replace usages of errors/index.js functions and adapt tests
- use logging.error, logging.warn
- make tests green
- remove some usages of logging and throwing api errors -> because when a request is involved, logging happens automatically
- 🐛 return errorDetails to Ghost-Admin
- errorDetails is used for Theme error handling
- 🎨 use 500er error for theme is missing error in theme-handler
- 🎨 extend file rotation to 1w
refs #7452
- remove references to 'patronus' in favour of GhostAuth, Note: this will require databases to be deleted ;)
- remove email addresses from test data
issue #7452
Remote oauth2 authentication with Ghost.org.
This PR supports:
- oauth2 login or local login
- authentication on blog setup
- authentication on invite
- normal authentication
- does not contain many, many tests, but we'll improve in the next alpha weeks