1

I am getting an error when I make a callout to Google Calendar, I could get the access token but when I call the method to insert an event I get this error:

{
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "required",
    "message": "Login Required",
    "locationType": "header",
    "location": "Authorization"
   }
  ],
  "code": 401,
  "message": "Login Required"
 }
}

This is my code:

        String token = get_access_token();
        final PageReference theUrl = new PageReference('https://www.googleapis.com/calendar/v3/calendars/xxxxxxxxxxxx%40gmail.com/events?acccess_token=' + token);

        String body = '';

        JSONGenerator gen = JSON.createGenerator(true);
        gen.writeStartObject();
        gen.writeFieldName('end');
        gen.writeStartObject();
        gen.writeStringField('dateTime', '2017-01-25T12:30:00');
        gen.writeStringField('timeZone', 'America/Lima');
        gen.writeEndObject();
        gen.writeFieldName('start');
        gen.writeStartObject();
        gen.writeStringField('dateTime', '2017-01-25T11:30:00');
        gen.writeStringField('timeZone', 'America/Lima');
        gen.writeEndObject();
        gen.writeStringField('summary', 'Test from Salesforce');
        gen.writeFieldName('attendees');
        gen.writeStartArray();
        gen.writeStartObject();
        gen.writeStringField('email', 'xxxxxx@xxxx.edu.pe');
        gen.writeStringField('responseStatus', 'needsAction');
        gen.writeStringField('displayName', 'xxxxxxxx');
        gen.writeEndObject();
        gen.writeStartObject();
        gen.writeStringField('email', 'xxxxxxxx@gmail.com');
        gen.writeStringField('responseStatus', 'accepted');
        gen.writeStringField('displayName', 'xxxxxxxxx');
        gen.writeBooleanField('organizer', true);
        gen.writeBooleanField('self', true);
        gen.writeEndObject();
        gen.writeEndArray();
        gen.writeEndObject();

        HttpRequest request = new HttpRequest();
        request.setEndpoint(theUrl.getUrl());
        request.setHeader('Content-Type', 'application/json');
        request.setMethod('POST');
        request.setTimeout(120000);
        request.setBody(gen.getAsString());        

        HttpResponse response = (new Http()).send(request);
        system.debug('#### getBody' + response.getBody());

public String get_access_token(){

        Http h = new Http();
        HttpRequest req = new HttpRequest();
        HttpResponse res = new HttpResponse();
        req.setEndpoint('https://accounts.google.com/o/oauth2/token');
        req.setMethod('POST');

        req.setHeader('ContentType','application/x-www-form-urlencoded');

        String header = '{"alg":"RS256","typ":"JWT"}';
        String header_encoded = EncodingUtil.base64Encode(blob.valueof(header));

        String claim_set = '{"iss":"XXXXXXXXXX-compute@developer.gserviceaccount.com"';
        claim_set += ',"scope":"https://www.googleapis.com/auth/calendar"';
        claim_set += ',"aud":"https://accounts.google.com/o/oauth2/token"';
        claim_set += ',"exp":"' + datetime.now().addHours(1).getTime()/1000;
        claim_set += '","iat":"' + datetime.now().getTime()/1000 + '"}';

        String claim_set_encoded = EncodingUtil.base64Encode(blob.valueof(claim_set));

        String signature_encoded = header_encoded + '.' + claim_set_encoded;

        String key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';

        blob private_key = EncodingUtil.base64Decode(key);
        signature_encoded = signature_encoded.replaceAll('=','');
        String signature_encoded_url = EncodingUtil.urlEncode(signature_encoded,'UTF-8');
        blob signature_blob = blob.valueof(signature_encoded_url);

        String signature_blob_string = EncodingUtil.base64Encode(Crypto.sign('RSA-SHA256', signature_blob, private_key));

        String JWT = signature_encoded + '.' + signature_blob_string;

        JWT = JWT.replaceAll('=','');

        String grant_string= 'urn:ietf:params:oauth:grant-type:jwt-bearer';
        req.setBody('grant_type=' + EncodingUtil.urlEncode(grant_string, 'UTF-8') + '&assertion=' + EncodingUtil.urlEncode(JWT, 'UTF-8'));
        res = h.send(req);
        String response_debug = res.getBody() +' '+ res.getStatusCode();
        System.debug('Response =' + response_debug );
        if(res.getStatusCode() == 200) {
            JSONParser parser = JSON.createParser(res.getBody());
            while (parser.nextToken() != null) {
                if ((parser.getCurrentToken() == JSONToken.FIELD_NAME) && (parser.getText() == 'access_token')) {
                    // Move to the value.
                    parser.nextToken();
                    // Return the access_token
                    return parser.getText();
                }
            }
        }
        return 'error';
    }

can any one help me?

1

A few things. I was able to get your example working with a service account. Since you're getting the token, I suspect the values you're passing to the service are not being accepted. My suggestion is to use the Google API Explorer to get the correct values.

Firstly, change final PageReference theUrl = new PageReference('https://www.googleapis.com/calendar/v3/calendars/xxxxxxxxxxxx%40gmail.com/events?acccess_token=' + token);

To final PageReference theUrl = new PageReference('https://www.googleapis.com/calendar/v3/calendars/primary/events');

You do need to pass the access token on the query string. This is already being passed as a value in HttpHeader.

Secondly, this is the JSON string I used to create a parameter.

String body = '{ "description": "Republic Day of India", "start": { "date": "2018-01-26", "timeZone": "America/Los_Angeles" }, "end": { "date": "2018-01-26", "timeZone": "America/Los_Angeles" }, "location": "200 Amphitheatre Dr, Mountain View, CA", "visibility": "public", "transparency": "opaque", "status": "confirmed", "summary": "India Day Celebrations", "reminders": { "useDefault": true } }';

The API Explorer I used to test my input is located at https://developers.google.com/google-apps/calendar/v3/reference/events/insert

|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.