Using OAuth 2
The Meetup API supports authenticating requests using OAuth 2 over HTTPS
.
We provide implementations a number of protocol flows outlined below. We provide the following endpoints for acquiring member authorization and access tokens.
Endpoint | URL |
---|---|
Authorization | https://secure.meetup.com/oauth2/authorize |
Access Tokens | https://secure.meetup.com/oauth2/access |
Redirect URIs
Before you can use OAuth 2 for member authorization, you need to either register a new OAuth client or add a redirect_uri
to an existing client by clicking the edit link next to you client's listing. The redirect_uri
you register for a given client will be used to validate future oauth2 requests.
This uri is used as a basis for validating the address authorization requests will redirect a member to after granting or denying access to your app.
If provided, the redirect URL's host and port must exactly match the callback URL. The redirect URL's path must reference a subdirectory of the callback URL.
CALLBACK: http://example.com/path
GOOD: http://example.com/path
GOOD: http://example.com/path/subdir/other
BAD: http://example.com/bar
BAD: http://example.com/
BAD: http://example.com:8080/path
Making requests
OAuth 2 authenticated requests expect an Authorization header with value in the following format.
Authorization: bearer {ACCESS_TOKEN}
Example
Authorization: bearer abcdefghijklmnop
You can obtain an access token using one of the following flows.
Server Flow
This flow is suitable for applications that are capable of securely storing consumer secrets and target interactive member authentication.
Requesting Authorization
Redirect your user to the following URL in a browser:
https://secure.meetup.com/oauth2/authorize?client_id={YOUR_CLIENT_KEY}&response_type=code&redirect_uri={YOUR_CLIENT_REDIRECT_URI}
The redirect_uri
used here may vary but must start with the same redirect_uri
you have registered with your consumer.
Meetup will ask the member to login if they are not already logged in. If the member has previously authorized access for the provided client_id
, Meetup will immediately redirect the member back to the redirect_uri
with success query parameters. If the authenticated member has not previously authorized the provided client or has revoked its access, Meetup will prompt them to authorize your application. Afterwords, Meetup will redirect the member back to the provided redirect_uri
along with their response.
A successful authorization will contain these query parameters:
Parameter | Description |
---|---|
code | A string that can only be used once to request an access token |
state | An opaque string that you may provide in the initial request |
A failed authorization will contain an optional state
parameter (mentioned above) as well as an error
query parameter with one of the following values:
Error | Reason |
---|---|
invalid_request | The request was malformed or missing parameters |
unauthorized_client | The client is not authorized |
access_denied | The user denied the request for authorization |
unsupported_response_type | Meetup doesn`t support the provided response_type |
4xx or 5xx | The HTTP status code of any other error |
Requesting Access Token
Have your server make an HTTP application/x-www-form-urlencoded
encoded POST request for an access token with the following format:
https://secure.meetup.com/oauth2/access
client_id={YOUR_CLIENT_KEY}
&client_secret={YOUR_CLIENT_SECRET}
&grant_type=authorization_code
&redirect_uri={SAME_REDIRECT_URI_USED_FOR_PREVIOUS_STEP}
&code={CODE_YOU_RECEIVED_FROM_THE_AUTHORIZATION_RESPONSE}
The important parameter to note is grant_type
which should be set to authorization_code
. The redirect_uri
used in this step must be the same redirect_uri
used in the previous step.
We also support the usage of query string parameters for this method.
A successful response will contain the following data in application/json
format
{
"access_token": "{ACCESS_TOKEN_TO_STORE}",
"token_type": "bearer",
"expires_in": 3600,
"refresh_token": "{TOKEN_USED_TO_REFRESH_AUTHORIZATION}"
}
A failure response will contain an application/json
encoded string with an error property containing one of the following values
Error | Reason |
---|---|
invalid_request | The request was malformed or missing parameters |
invalid_client | Client authentication failed |
unauthorized_client | The client is not authorized |
invalid_grant | The provided code was invalid |
unsupported_grant_type | Meetup does not support the provided grant type |
Refresh Token Flow
Access tokens may expire after a period of time. This flow allows you to refresh your credentials, exchanging one set for another.
Requesting Access Token
Have your server make an HTTP application/x-www-form-urlencoded
encoded POST request for an access token with the following format:
https://secure.meetup.com/oauth2/access
client_id={YOUR_CLIENT_KEY}
&client_secret={YOUR_CLIENT_SECRET}
&grant_type=refresh_token
&refresh_token={REFRESH_TOKEN_FROM_PREVIOUS_CREDENTIALS}
A successful response will contain the following data in application/json
format
{
"access_token": "{NEW_ACCESS_TOKEN_TO_STORE}",
"token_type": "bearer",
"expires_in": 3600,
"refresh_token": "{TOKEN_USED_TO_REFRESH_AUTHORIZATION}"
}
A failure response will contain an application/json
encoded string with an error property containing one of the following values
Error | Reason |
---|---|
invalid_request | The request was malformed or missing parameters |
invalid_client | Client authentication failed |
unauthorized_client | The client is not authorized |
invalid_grant | The provided code was invalid |
unsupported_grant_type | Meetup does not support the provided grant type |
JWT Flow
This flow is suitable for applications that are server to server based and expect no member interaction. In this flow, member authorization is limited to the owner of the OAuth Client.
Requesting Access Token
Have your server make an HTTP application/x-www-form-urlencoded
encoded POST request for an access token with the following format:
https://secure.meetup.com/oauth2/access
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
&assertion={SIGNED_JWT}
The SIGNED_JWT should be a JWT signed with a private RSA key obtained from a previous signing key creation step on your OAuth Client settings page which includes the following JWT claim fields
{
"sub": "{AUTHORIZED_MEMBER_ID}",
"iss": "{YOUR_CLIENT_KEY}",
"aud": "api.meetup.com",
"exp": "{EXPIRATION_TIME_IN_SECONDS}"
}
The AUTHORIZED_MEMBER_ID is the member id the access token is intended to act on behalf of. At this time, this member id must be the member id that owns the OAuth Client.
To identify which private key was used to sign a given request, refer to the signing key id in the JWT kid
header field, noted as SIGNING_KEY_ID below
{
"kid": "{SIGNING_KEY_ID}",
"typ": "JWT",
"alg": "RS256"
}
Below is an example of generating a JWT in node using the jsonwebtoken npm package.
const jwt = require('jsonwebtoken');
const fs = require('fs');
const privateKey = fs.readFileSync('path/to/private.key');
jwt.sign(
{},
privateKey,
{
algorithm: 'RS256',
issuer: '{YOUR_CONSUMER_KEY}',
subject: '{AUTHORIZED_MEMBER_ID}',
audience: 'api.meetup.com',
keyid: '{SIGNING_KEY_ID}',
expiresIn: 120
}
);
Below is an example of generating a JWT in java using the maven central hosted library for nimbus-jose-jwt. Be sure to include the following bouncy castle libraries which provide proper RSA PEM file parsing behavior bcprov-jdk18on, bcpkix-jdk18on.
import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.*;
import com.nimbusds.jose.jwk.*;
import com.nimbusds.jwt.*;
import java.time.Instant;
import java.util.Date;
import java.nio.file.*;
var jwk = JWK.parseFromPEMEncodedObjects(
Files.readString(Paths.get("path/to/private.key"))
);
var jwt =
new SignedJWT(
new JWSHeader.Builder(JWSAlgorithm.RS256)
.type(JOSEObjectType.JWT)
.keyID("{SIGNING_KEY_ID}")
.build(),
new JWTClaimsSet.Builder()
.issuer("{YOUR_CLIENT_KEY}")
.subject("{AUTHORIZED_MEMBER_ID}")
.audience("api.meetup.com")
.expirationTime(Date.from(Instant.now().plusSeconds(120)))
.build()
);
jwt.sign(new RSASSASigner(RSAKey.parse(jwk.toJSONString())));
jwt.serialize();
A successful response will contain the following data in application/json
format
{
"access_token": "NEW_ACCESS_TOKEN_TO_STORE",
"token_type": "bearer",
"expires_in": 3600,
"refresh_token": "TOKEN_USED_TO_REFRESH_AUTHORIZATION"
}
A failure response will contain an application/json
encoded string with an error property containing one of the following values
Error | Reason |
---|---|
invalid_request | The request was malformed or missing parameters |
invalid_client | Client authentication failed |
unauthorized_client | The client is not authorized |
invalid_grant | The provided code was invalid |
unsupported_grant_type | Meetup does not support the provided grant type |
Implicit Flow
This flow is suitable for JavaScript based browser clients and target interactive member authentication.
Requesting Authorization and Receiving Access Token
Redirect the user`s browser to the following URL
https://secure.meetup.com/oauth2/authorize?client_id={YOUR_CLIENT_KEY}&response_type=token&redirect_uri={YOUR_CLIENT_REDIRECT_URI}
This will ask the user to log in if they are not already logged in and prompt them to authorize your application.
The response parameters listed in the server flow`s success (with the exception of refresh_token
) and failure access token responses will be included in the implicit authorization`s client response appended as a url fragment. Because this information is encoded in a url fragment, it can only be retrieved with client-side browser scripts.