Every resource of the Weather API is secured via OAuth 2.0. Each request requires a valid token from our central authorisation server. These tokens have a validity period of one hour.
The Required client credentials for this authentication can be requested via this form.
Authorisation is obtained using OAuth 2.0 client_credentials grant type (see also RFC6749: "The OAuth 2.0 Authorization Framework" section 4.4).
####The following grapic visualises the basic flow.
-
In order to authenticate for the authorization request, the client has to provide client credentials (i.e.
client_id
andclient_secret
) asuserid
andpassword
via HTTP Basic Authentication. -
After successful authentication the client retrieves an authentication token as response. This access token comes in the form of a JSON Web Token (JWT).
-
The access token can now be used to access Weather API Resources. The access token therefore is submitted as HTTP
Authorization
header of typeBearer
, when requesting against any resource.
The access token can be reused for multiple requests until it expires (which will happen one hour after it was issued).
Authorization Request:
POST /oauth/token HTTP/1.1
Authorization: ***** HTTP basic authentication with client_id and client_secret *****
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Host: auth.weather.mg
Connection: close
grant_type=client_credentials
Authorization Response:
HTTP/1.1 200
Cache-Control: no-store
Pragma: no-cache
Content-Type: application/json;charset=UTF-8
Connection: close
{
"access_token": "JWT_ACCESS_TOKEN",
"token_type": "bearer",
"expires_in": 3600,
"scope": "space separated list of allowed scopes",
"domain": "meteogroup",
"jti": "id of JWT_ACCESS_TOKEN"
}
Resource Request:
GET /observation?location=53,13 HTTP/1.1
Authorization: Bearer JWT_ACCESS_TOKEN
Host: api.weather.mg
Connection: close
Resource Response omitted
For an implementation in Java we recommend the usage of Zalandos open source tokens
library (see https://github.com/zalando/tokens for details).
AccessTokens accessTokens = Tokens.createAccessTokensWithUri(new URI("https://auth.weather.mg/oauth/token"))
.usingClientCredentialsProvider(() -> new SimpleClientCredentials("your_client_id", "your_client_secret"))
.usingUserCredentialsProvider(() -> null)
.manageToken("token_name")
.withGrantType("client_credentials")
.done()
.start();
The created accessTokens
instance now handles the management for the tokens transparently.
By calling accessTokens.get("token_name")
a valid token is provided. Per default that token has at least 40% of lifetime remaining (which in this case would mean 24 minutes). Whenever the lifetime falls below that (configurable) value a new token is requested in the background.
To use the token in a request, set the token as Bearer
in the Authorization
header.
/**
* example with Apache HTTP Client
*/
final String accessToken = accessTokens.get("token_name")
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet get = new HttpGet("https://api.weather.mg/observation?location=53,13");
get.setHeader("Authorization", "Bearer " + accessToken);
CloseableHttpResponse httpResponse = httpClient.execute(get);
// process response...
/**
* example with Spring Resttemplate
*/
final String accessToken = accessTokens.get("token_name")
HttpHeaders headers = new HttpHeaders();
headers.set(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken);
HttpEntity entity = new HttpEntity<>(headers);
ResponseEntity<ResponseType> response = restTemplate.exchange(entity, ResponseType.class);
// process response...
Here is a simple implementation example in NodeJS with request.
var request = require('request');
request({
url: 'https://auth.weather.mg/oauth/token',
method: 'POST',
auth: {
user: 'your_client_id', // replace 'your_client_id' with your own ClientId
pass: 'your_client_secret' // replace 'your_client_secret' with your own ClientSecret
},
form: {
'grant_type': 'client_credentials'
}
}, function (error, response, body) {
if (error) {
console.error(error);
} else {
var body = JSON.parse(body);
console.log(body);
}
});
Response
{
access_token: 'eyJraWQiOiJhdXRoLXNlcnZlci1iODA5MzIwMS03MjNkLTazZTgtYTgwMC1iOWU0ZTFjMDIxMGQiLCJhbGciOiJSUzI1NiJ1.eyJzdWIiOiJhbmRyZS5zY2hhZGUiLCJzY29wZSI6WyJwb2ludC1vYnNlcnZhdGlvbiIsInBvaW50LWZvcmVjYXN0Il0sImRvbWFpbiI6Im1ldGVvZ3JvdXAiLCJleHAiOjE0ODkxNDQyMTIsImp0aSI6IjZjZTJmYzlkLWUxYWEtNGNhMy04NzQ5LWI0NGU0ZWQ5MzdjZCIsImNsaWVudF8pZCI7ImFuZHJlLnNjaGFkZSJ9.XC8spP9mQICozXpmFx8PE8RFtKeZ1M0CNp0MWPMtqD3XiWp8ve1FJ_qoPImTbsS0QUlmvquGf3j0A8QeQ5QJyQ',
token_type: 'bearer',
expires_in: 3599,
scope: 'point-observation point-forecast',
domain: 'meteogroup',
jti: '6ce2fc9d-e1aa-4ca3-8749-b44e4ed937cd'
}
That is a sample request then for the point observation service for the latest values only which uses dateformat to calculate the necessary timestamp for the observedFrom query parameter. This example ask diectly for a MeteoGroup station instead of asking for a location with latitude and longitude.
var request = require('request'),
dateformat = require('dateformat'),
observedFromDate = new Date();
observedFromDate.setHours(observedFromDate.getHours() - 1);
request({
url: 'https://point-observation.weather.mg/search',
auth: {
'bearer': 'OAuth2_token' //replace that with the token you got from the auth process
},
qs: {
meteoGroupStationIds: 10853,
observedFrom: dateformat(observedFromDate, "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"),
observedPeriod: "PT0S,PT1H",
fields: "airTemperatureInCelsius,feelsLikeTemperatureInCelsius,airPressureInHectoPascal,windSpeedInKnots,windDirectionInDegree,dewPointTemperatureInCelsius,relativeHumidityInPercent,effectiveCloudCoverInOcta,totalCloudCoverInOcta,weatherCode,weatherCodeTraditional,windGustInKnots,precipitationAmountInMillimeter"
}
}, function (error, response, body) {
if (error) {
console.error(error)
} else {
console.log(JSON.parse(body));
}
});
Response
{
observations: [
{
meteoGroupStationId: '10853',
observedFrom: '2017-03-09T20:00:00Z',
observedUntil: '2017-03-09T20:00:00Z',
observedPeriod: 'PT0S',
airTemperatureInCelsius: 9.7,
feelsLikeTemperatureInCelsius: 7.6,
airPressureInHectoPascal: 1018.8,
windSpeedInKnots: 13.606908,
windDirectionInDegree: 270,
dewPointTemperatureInCelsius: 7.6,
relativeHumidityInPercent: 87,
effectiveCloudCoverInOcta: 7,
totalCloudCoverInOcta: 7,
weatherCode: '508',
weatherCodeTraditional: 0
}
]
}
Access token configuration in Postman: