Skip to content

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.

EndpointURL
Authorizationhttps://secure.meetup.com/oauth2/authorize
Access Tokenshttps://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:

ParameterDescription
codeA string that can only be used once to request an access token
stateAn 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:

ErrorReason
invalid_requestThe request was malformed or missing parameters
unauthorized_clientThe client is not authorized
access_deniedThe user denied the request for authorization
unsupported_response_typeMeetup doesn`t support the provided response_type
4xx or 5xxThe 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

ErrorReason
invalid_requestThe request was malformed or missing parameters
invalid_clientClient authentication failed
unauthorized_clientThe client is not authorized
invalid_grantThe provided code was invalid
unsupported_grant_typeMeetup 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

ErrorReason
invalid_requestThe request was malformed or missing parameters
invalid_clientClient authentication failed
unauthorized_clientThe client is not authorized
invalid_grantThe provided code was invalid
unsupported_grant_typeMeetup 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

ErrorReason
invalid_requestThe request was malformed or missing parameters
invalid_clientClient authentication failed
unauthorized_clientThe client is not authorized
invalid_grantThe provided code was invalid
unsupported_grant_typeMeetup 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.