JWT - Verify Token given a public key - genexus

I need to create a Rest API that receives a JWT token and I need to validate it with a given public key.
"They must validate the "Bearer Token" sent in the header of
requests using a public key provided according to the environment, as well as verifying the
scope user availability. Consult "
The public key:
http://desenv.authenticador.sp.gov.br/.well-known/jwks
I tried using DoVerify() but I don't know where to enter the public key.
&token = &HttpRequest.GetHeader('Authorization')
if not &token.IsEmpty()
&token = &token.Replace("Bearer ", "")
&result = &JWTCreator.DoVerify(&token, JWTAlgorithm.RS256, &privateClaims, &JWTOptions)
if &result
&mensagem = 'token is valid'
else
&mensagem = "token is NOT valid"
If &JWTCreator.HasError()
&codigo = &JWTCreator.GetErrorCode().ToNumeric()
&mensagem = &JWTCreator.GetErrorDescription()
EndIf
endif
else
&codigo = 401
&mensagem = "Token not found!"
endif
Any suggestions?
Thanks

If you already have a token, use that in jet.io to encode the first part of the key. Is the jwt token created by your application? - if so then you probably might have included a public key in the first part of the jwt token.

Load the certificate using the Certificate type. The function will depend on the format of the cert.
Then, add it to the JWTOptions
Also, it looks like the DoVerifyJustSignature is the function you want to use in that case.

I solved this problem as follows:
A procedure that expects a token and returns a code and a message.
parm(in:&jwt_token, out:&codigo, out:&mensagem);
Source:
&codigo = 0
&mensagem = ''
if not &jwt_token.IsEmpty() and &jwt_token.Contains('Bearer')
&token = &jwt_token.Replace("Bearer ", "")
// capturar o payload do token e o header para comparar com o que temos na chave publica.
&payload = &JWTCreator.GetPayload(&token)
&header = &JWTCreator.GetHeader(&token)
// carregar o payload e header no SDT.
&SDTJWTOptions.header.FromJson(&header)
&SDTJWTOptions.payload.FromJson(&payload)
// Validar se o token é compátivel com a chave publica disponibilizada.
&ChavePub_SDTJWTOptions.header.FromJson('{"typ": "JWT","alg": "RS256","x5t": "vST_OxZ0TJ5w3miLGWJ7xlH8sZo","kid": "vST_OxZ0TJ5w3miLGWJ7xlH8sZo"}')
If (&SDTJWTOptions.header.alg <> &ChavePub_SDTJWTOptions.header.alg) or
(&SDTJWTOptions.header.typ <> &ChavePub_SDTJWTOptions.header.typ) or
(&SDTJWTOptions.header.x5t <> &ChavePub_SDTJWTOptions.header.x5t) or
(&SDTJWTOptions.header.kid <> &ChavePub_SDTJWTOptions.header.kid)
&codigo = 401
&mensagem = "Token Inválido!" // existe um Bearer Token inválido;
Return
EndIf
// Validar se o token está com a data de expiração válida.
// A data do token é em formato UNIX que faz necessário a conversão.
// - Data UNIX inicia em 1/1/1970 as 00:00:00
// - Com a data UNIX formatada, adicionar a expiração em UNIX como segundos.
&Datetime = YMDHMStoT(1970, 1, 1, 00, 00, 00)
&NowDatetime = ServerNow()
&TokenDatetime = &Datetime.AddSeconds(&SDTJWTOptions.payload.exp)
// Valida se o retorno da diferença das datas (atual vs token) é menor que 0,
// indicando que a data de expiração já passou e é inválida.
&Diff = &TokenDatetime.Difference(&NowDatetime)
If &Diff <= 0
&codigo = 401
&mensagem = "Token Expirado!" // existe um Bearer Token válido, porém está expirado;
EndIf
Else
&codigo = 401
&mensagem = "Requisição sem token de autorização" // não encontrado o Bearer Token no header;
EndIf
Return

Related

Google Push notification giving ParseError

I am trying to use google push notification for calendar to be notified if a user's event's start or/and end dateTime changes.
I have followed all the steps from push doc regarding registering and verifying my domain.
My code is as follows:
#blueprint.route("/notifications", methods={'GET','POST'})
def timeBlocker():
email = '....#gmail.com'
user = User.query.filter_by(email=email).first()
thecredentials = {
'client_id': os.getenv('client_id'),
'client_secret':os.getenv('client_secret'),
'refresh_token':user.refresh,
'grant_type': 'refresh_token',
}
req = requests.post(url='https://oauth2.googleapis.com/token', data = thecredentials)
req_ = req.json()
accessToken = req_["access_token"]
print('access token is ' + accessToken)
body = {
'id': '01234567-89ab-cdef-0123456789ab',
'type': 'web_hook',
'address': 'https://dayliii.com/notifications'
}
headers = {'Authorization': 'Bearer ' + accessToken,
'Content-Type': 'application/json'
}
calendar = '....#group.calendar.google.com'
req = requests.post(url='https://www.googleapis.com/calendar/v3/calendars/....#group.calendar.google.com/events/watch', data = body, headers=headers)
return str(req.json())
Error:
{'error': {'errors': [{'domain': 'global', 'reason': 'parseError', 'message': 'Parse Error'}], 'code': 400, 'message': 'Parse Error'}}
I tried converting from double quotes to single quote as this similar post suggested yet it didn't work.
Lastly, I was curious to know if I should register & verify domain ownership of 'http://localhost:5000/' when working with push notifications in dev mode? As that's the error I am expecting to get that not sure about the way around it.
The data parameter in request() function accepts json format.
You can try converting your body variable into a json string using json.dumps().
Your request code should look like this:
req = requests.post(url='https://www.googleapis.com/calendar/v3/calendars/....#group.calendar.google.com/events/watch', data = json.dumps(body), headers=headers)

JWT token does not begin with Bearer String

I got a warning message like this "JWT token does not begin with Bearer String" before I generate the token, and it's also more warning like this when I open swagger.
your have to provide the Bearer String,
must of the libraries out there provide and automatic way of doing that,
for example with io.jsonwebtoken
long now = (new Date()).getTime();
String token = Jwts.builder()
.setSubject("username")
.claim("roles", "ROLE_ADMIN, ROLE_USER")
.signWith(key, SignatureAlgorithm.HS512)
.setExpiration(new Date(now + 86400))
.compact();
here token starts with Bearer

How to send new direct message through Twitter API https://api.twitter.com/1.1/direct_messages/events/new.json?

I am implementing Twitter new Direct message API,
https://api.twitter.com/1.1/direct_messages/events/new.json
I am facing error,
415 Unsupported Media Type
I am able to call it via TWURL tool and currently I am sending simple text message through it.
From error code, I understand that either there is content-type issue or payload is in incorrect format.
I am passing payload as,
options = {
"event": {
"type": "message_create",
"message_create": {
"target": {
"recipient_id": "1234"
},
"message_data": {
"text": "test"
}
}
}
}
Payload is converted to usual Ruby hash, i.e. :key => "value"
{:event=>
{:type=>"message_create",
:message_create=>
{:target=>{:recipient_id=>"1234"},
:message_data=>{:text=>"test"}}}}
How to preserve third party API request format?
Any suggestion will be great help.
Thanks
Have you tried setting Content-Type ('application/json')? in your content header before sending?
It is one of the most common issues.
You can do so by doing something similar to:
before_filter :set_content_type
def set_content_type
#headers["Content-Type"] = "application/json; charset=utf-8"
end
It will force your application to append the Content-Type on each request.
https://github.com/J7mbo/twitter-api-php/blob/master/TwitterAPIExchange.php
usa la clase TwitterAPIExchange y aplica estos cambios.
Yo lo solucione modificando la clase así:
a la clase TwitterAPIExchange , añade la propiedad
public $appjson;
en public function __construct(array $settings) añade la inicialización.
$this->appjson=false;
en public function performRequest($return = true, $curlOptions = array())
remplaza
$header = array($this->buildAuthorizationHeader($this->oauth), 'Expect:');
por
if ($this->appjson) {
$header = array('Content-Type: application/json',$this->buildAuthorizationHeader($this->oauth), 'Expect:');
} else {
$header = array($this->buildAuthorizationHeader($this->oauth), 'Expect:');
}
para finalizar usa:
.....
$twitter = new TwitterAPIExchange($settings);
......
......
$twitter->appjson=true;
$twitter->buildOauth($url, $requestMethod)
->performRequest(true,
array( CURLOPT_POSTFIELDS => $params)
);
I got similar error and it turned out the data format I was sending the request in was a bit wrong. I was using python requests with the following headers:
HEADERS = {
'Content-type': 'application/json',
'Accept': 'application/json'
}
But still using json.dumps() on the actual data, the request was subsequently inconsistent with bad data, it all worked when I just sent the data without dumps'ing it.
This might not really help but just check your data integrity.

Oracle MAF-MCS API call

I have created a custom POST api for getting login information in MCS. when i check in SOAPUI it works perfectly fine. the parameters passed are
1. header
Oracle-Mobile-Backend-Id: ********************
2. Authentocation
Username:****************
password: **************
and basic login info username and password as "User1" and "user1" respectively.
Step2:
when i call the API from MAF i am getting an error 400
the post method used is
public static Response callPost(String restURI, String jsonRequest) {
String responseJson = "";
Response response = new Response();
RestServiceAdapter restServiceAdapter = Model.createRestServiceAdapter();
restServiceAdapter.clearRequestProperties();
//restServiceAdapter.setConnectionName("MiddlewareAPI");
// restServiceAdapter.setConnectionName("");
restServiceAdapter.setRequestType(RestServiceAdapter.REQUEST_TYPE_POST);
restServiceAdapter.addRequestProperty("Content-Type", "application/json");
restServiceAdapter.addRequestProperty("Accept", "application/json; charset=UTF-8");
restServiceAdapter.addRequestProperty("Oracle-Mobile-Backend-Id", "**********");
restServiceAdapter.addRequestProperty("Domain", "mcsdem0001");
restServiceAdapter.addRequestProperty("Username", "******");
restServiceAdapter.addRequestProperty("Password", "*****");
//restServiceAdapter.addRequestProperty("Authorization", "Basic "+new String(encodedBytes));
System.out.println("**** Authorization String ****=>"+new String(encodedBytes));
System.out.println("**** RestURI ******=>"+restURI);
System.out.println("**** jsonRequest ******=>"+jsonRequest);
restServiceAdapter.setRequestURI(restURI);
restServiceAdapter.setRetryLimit(0);
try {
responseJson = restServiceAdapter.send(jsonRequest);
int responseCode = restServiceAdapter.getResponseStatus();
response.setResponseCode(responseCode);
response.setResponseMessage(responseJson);
response.setHeader(restServiceAdapter.getResponseHeaders());
} catch (Exception e) {
int responseCode = restServiceAdapter.getResponseStatus();
response.setResponseCode(responseCode);
response.setResponseMessage(responseJson);
}
System.out.println("Response:" + responseJson);
return response;
}
Could anyone please tell me is there any error in the post method??
This can be due to the version conflict. Try to use HttpUrlConnection instead of RestServiceAdapter and let me know if it works.
actually this bit
restServiceAdapter.addRequestProperty("Username", "******");
restServiceAdapter.addRequestProperty("Password", "*****");
doesn't work because you attempt to pass username and password as a HTTP header. Instead it should be passed as you were trying here
restServiceAdapter.addRequestProperty("Authorization", "Basic "+new String(encodedBytes));
However, these should not be encoded bytes but a base64 encoded string in the form
Basis (without the < abd >)
Note that user identity domains only need to be provided in multi-tenant environments. In MCS, the user domain is defined through the mobile backend you connect to.
Frank
Use the MAF MCS Utility library to make it allot easier.
The developer guide can be found here: http://download.oracle.com/otn_hosted_doc/maf/mafmcsutility-api-doc-082015.pdf
Example code:
MBEConfiguration mbeConfiguration =
new MBEConfiguration(
<mbe rest connection>,<mobileBackendId>,
<anonymous key string>,<application key string>,
MBEConfiguration.AuthenticationType.BASIC_AUTH);
mbeConfiguration.setEnableAnalytics(true);
mbeConfiguration.setLoggingEnabled(false)
mbeConfiguration.setMobileDeviceId(
DeviceManagerFactory.getDeviceManager().getName());
MBE mobileBackend = MBEManager.getManager().
createOrRenewMobileBackend(<mobile backend Id>, mbeConfiguration);
CustomAPI customApiProxy = mbe.getServiceProxyCustomApi();
MCSRequest request = new MCSRequest(mobileBackend.getMbeConfiguration());
request.setConnectionName(<Rest connection name>);
request.setRequestURI("/moile/custom/mockup/employees");
request.setHttpMethod(MCSRequest.HttpMethod.POST);
request.setPayload("{\"id\":\"1\"\"name\":\"nimphius\",\"firstName\":\"frank\"}");
request.setRetryLimit(0);
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Content-Type","application/json");
request.setHttpHeaders(headers);
MCSResponse response = customApiProxy .sendForStringResponse(request);
String jsonResponse = (String) response.getMessage();

Cookie is not being deleted

I've seen other questions of this problem, but nothing solved my problem:
I'm using cakephp, the code for setting/unsetting cookies is on AppController -> beforeFilter() to make sure it works correctly (is going to be the first portion of code to be executed before the actual page)
Let's see... for the login:
if($data['check'] == 'on')
$_SESSION['cookieActivation'] = 0;
$this->redirect(array('controller' => 'info', 'action' => 'index'));
For beforeFilter()
session_start();
//Esto es para eliminar la cookie, si la hay, y también sacar la sesión (deslogear)
if (isset($_SESSION['cookieRemoval']))
{
if (isset($_COOKIE['user'])) //está la cookie, en primer lugar?
{
unset($_COOKIE['user']);
setcookie('user','',1);
}
unset($_SESSION['cookieRemoval']);
}
//esto se setea si el tipo puso recordar contraseña en el login de dreyfus, se hace acá porque
//es el lugar correcto para setear la cookie, si se intenta hacer después, no funciona
if(isset($_SESSION['cookieActivation']))
if($_SESSION['cookieActivation'] == 0) //cero significa que quiere setear cookie porque todavía no lo hizo...
{
//si quiere que recuerden su login, hacemos una cookie
//va a expirar en 30 días... 3600 es una hora....
$_SESSION['cookieActivation'] = 1;
setcookie('user','pass',time()+(3600*30*24));
}
for logout
$_SESSION['cookieRemoval'] = 1; //avisa a appcontroller que quiere borrar la cookie de sesión...
$this->redirect(array('controller' => 'info', 'action' => 'login'));
Ok, that's a lot of code, let me explain it a bit:
If you do login, it sets a session variable to state that you want to set a cookie.
Then in it goes to beforefilter, it checks that you actually want to set a cookie, and it sets it for 30 days.
when you do logout, a session variable is created to specify that you want to remove the cookie, then it goes to beforefilter and then it detects that session variable and removes the cookie.
It works well, it redirects to a login page and with a printr the results are that I no longer have the cookie set... BUT, if I do F5 or close the browser and open the page again... the cookie is still there.
Any... tips here?
I solved this problem by being extra specific when setting the cookie, like this:
Create cookie:
setcookie('user','pass',time()+(3600*30*24), '/', $_SERVER['SERVER_NAME']);
Delete cookie:
setcookie('user','',1, '/', $_SERVER['SERVER_NAME']);
I basically added those last two fields...

Resources