I am trying to use FusionAuth's passwordless login feature. I am getting an error "Invalid redirect uri", when I try clicking on the link in the received email. I am using the php client.
$request = array();
$request["applicationId"] = $_SESSION['applicationID'];
$request["loginId"] = $email;
$target="http://8615582f3e2c.ngrok.io/index.php/Configure/MyFormEmployees";
$request["state"]["redirect_uri"] = $target;
$request["state"]["client_id"]=$_SESSION['applicationID'];
$request["state"]["response_type"]= "code";
$request["state"]["scope"]= "openid";
$request["state"]["state"]= "CSRF123";
$requestJ = json_encode($request); //convert the array into json
$result = $_SESSION['client']->startPasswordlesslogin($requestJ);
And this is what I am getting in the email as a link:
http://localhost:9011/oauth2/passwordless/5NHh37raOrUpSO4TlJcL-pY39i1TdasNd9vTTqqaiLk?tenantId=34303566-6466-3234-6565-656233663263&client_id=32688330-1630-4e0d-a4de-8ae45c3ca527&redirect_uri=http%3A%2F%2FXX15582f3e2c.ngrok.io%2Findex.php%2FConfigure%2FMyFormEmployees&response_type=code&scope=openid&state=CSRF123
and this causes the invalid URI error. How can I get this link to work?
You'll need to add http://XX15582f3e2c.ngrok.io/index.php/Configure/MyFormEmployees to the list of Authorized redirect URIs. In the FusionAuth console, see Applications > Edit > OAuth > Authorized redirect URLs.
Related
I have read many posts, all the Google documentation I can find and tried many iterations of the following and still can't get an access and refresh token. I do get an authorization code but can't seem to get that to trade for the access and refresh tokens.
if(authCode == null || authCode.equals("")) {
String url = "https://accounts.google.com/o/oauth2/v2/auth?"
+ "scope=https://mail.google.com/&"
+ "response_type=code&"
+ "redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&"
+ "client_id=" + clientId +
"&access_type=offline";
URI uri = new URI(url);
logger.debug("URI for auth is: " + uri);
if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
Desktop.getDesktop().browse(uri);
}
}
else {
logger.debug("Refreshing");
initRefreshToken();
}
With that, I get an access code I can cut and paste (just testing and trying to get this to work first) in my properties to get the refresh and access token.
In the initRefreshToken() method, the source is like this:
if(refreshToken.equals("")) {
logger.debug("Getting refresh token");
HttpPost post = new HttpPost("https://oauth2.googleapis.com/token");
// add request parameter, form parameters
List<NameValuePair> urlParameters = new ArrayList<>();
urlParameters.add(new BasicNameValuePair("code", authCode));
urlParameters.add(new BasicNameValuePair("client_id", clientId));
urlParameters.add(new BasicNameValuePair("client_secret", clientSecret));
urlParameters.add(new BasicNameValuePair("redirect_uri", "http://localhost:8000/"));
urlParameters.add(new BasicNameValuePair("grant_type", "authorization_code"));
try {
post.setEntity(new UrlEncodedFormEntity(urlParameters));
System.out.println("***** URL: " + urlParameters);
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = httpClient.execute(post);
System.out.println(EntityUtils.toString(response.getEntity()));
}
If this is a second or subsequent time using the code, what will be printed is:
Refersh token:
***** URL: [code=4/1AY0e-g..., client_id=370...i1h2u1s.apps.googleusercontent.com, client_secret=bAOH..., redirect_uri=https://localhost:8000/, grant_type=authorization_code]
{
"error": "invalid_grant",
"error_description": "Bad Request"
}
If the code is run and it's the first time using an authentication code, it will print:
{
"error": "redirect_uri_mismatch",
"error_description": "Bad Request"
}
I read in the Google console that exceptions are made for localhost domains so there's no need to register them. However, if there were a need to register them, it won't let you register them anyway as a domain must be a top level domain you own in order to register it. Therefore, how do I register localhost and/or exchange an authorization code for an access and refresh token in Java?
Thank you for your help.
DaImTo provided a great video about this and in that video and the blog post associated with it, the redirect_uri is listed correctly as: "urn:ietf:wg:oauth:2.0:oob". I didn't find this in the documentation but when I added it to my source code, I got access and refresh tokens as a response. Thank you very much for that help, DaImTo.
My code:
if ($client->getAccessToken()) {
$_SESSION['access_token'] = $client->getAccessToken();
$obj_token = json_decode($client->getAccessToken());
$accessToken = $obj_token->access_token;
$token_data = $client->verifyIdToken($accessToken)->getAttributes();
}
Error:
Uncaught exception 'Google_Auth_Exception' with message 'Wrong number of segments in token: ya29.qQH27NhAXVXPJ64txBjhT_j1FNaVCjosyfwUFKpgsn9LBiyNDS7wgDXVDR31y9hvFbM824mrzOcrWA'
$accessToken should be a string with 2 "." but i don't know why $token_data return a29.qQH27NhAXVXPJ64txBjhT_j1FNaVCjosyfwUFKpgsn9LBiyNDS7wgDXVDR31y9hvFbM824mrzOcrWA', that only have 1 "."
You're trying to verify an access_token as an id_token. They are different tokens, serving different purposes. For an id_token example see the code at https://github.com/google/google-api-php-client/blob/master/examples/idtoken.php, so:
$token_data = $client->verifyIdToken()->getAttributes();
assuming that an id_token was returned by Google as part of the handshake in the first place.
Front end is 100% JS. User click on sign in button and an authResult['code'] is received and send via ajax to localhost/api/user/login which has the following content:
$code = $data['code'];
require_once 'Google/Client.php';
$client = new Google_Client();
$client->setClientId('xxxxxx');
$client->setClientSecret('xxxxx');
$client->setRedirectUri('http://localhost:8080');
$client->setScopes('email'); //Why do I need this? I already set scope in JS.
$client->authenticate($code); //It fails here. with no error. just 400 bad request.
$token = json_decode($client->getAccessToken());
$reqUrl = 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=' .
$token->access_token;
$req = new Google_HttpRequest($reqUrl);
$tokenInfo = json_decode(
$client::getIo()->authenticatedRequest($req)->getResponseBody());
//Check errors.
//Save user personal info in database
//Set login sessions
Why do I need to set scopes if I already set them in javascript?
Why is it failing when authenticate function is called? Im getting no erros.
Why do I need a setRedirectUri() when it is on the backend?
You don't need to set scopes in this case.
(see answer 3, but also): Check your client ID matches the one used in the Javascript, and that the client secret is exactly as in the console (no trailing/leading spaces).
Changing your redirecturi to 'postmessage' - this is the string used when the code was generated via the Javascript process.
You can also try manually constructing the URL and calling it with curl to make sure everything is as you expect: https://developers.google.com/accounts/docs/OAuth2WebServer#handlingtheresponse
I am trying to authentify a domain for google docs scope. This is the url:
https://www.google.com/accounts/AuthSubRequest?next=http%3A%2F%2Fwww.mydomain.edu.au%2Fcomponents%2Fgoogle%2FretrieveToken.php&scope=https%3A%2F%2Fdocs.google.com%2Ffeeds%2F&session=1&secure=0&hd=default
So my domain is: www.mydomain.edu.au
But when makng the request Then i get this answer:
The page you have requested cannot be displayed. Another site was requesting access to your Google Account, but sent a malformed request. Please contact the site that you were trying to use when you received this message to inform them of the error. A detailed error message follows:
The site "http://edu.au" has not been registered.
So its identified as edu.au domain.
Is there a way around this?
Thanx
sample code for uploading document to google docs:
public static function uploadDocs($data = array())
{
if (!self::checkInput($data)) return false;
$data['url'] = Google::docsAPIUrl.'default/private/full'.self::getFolder($data['folderId']);
//"?convert=false"
$headers = Google::getAuthToken();
array_push($headers, Google::getGData());
$contentHeaders = self::getInputHeaders($data);
array_push($headers, 'Content-Length: '.$contentHeaders['length']);
array_push($headers, 'Content-Type: '.$contentHeaders['type']);
array_push($headers, 'Slug: '.Html::win2utf8($data['docTitle']));
if ($data['inputMethod'] == 'File')
{
$data['input'] = ((fread(fopen($data['input'], 'rb'), filesize($data['input']))));
}
$curl = Google::curl($data['url'], null, $data['input'], $headers);
if (Curl::checkCode($curl['code']))
{
return self::parseNewXML($curl['response']);
}
else
{
Google::$error = array('errorCode'=>$curl['code'],'errorString'=>$curl['response']);
return false;
}
}
AuthSub is deprecated. You should be using OAuth 2.0 and Drive API v2.
I am building a google contextual gadget in it i use the following code to load a page:
var params = {};
url = "http://example.com:2057/tasks/create";
params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.JSON;
params[gadgets.io.RequestParameters.AUTHORIZATION] = gadgets.io.AuthorizationType.SIGNED;
params["OAUTH_SERVICE_NAME"] = "HMAC";
params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.GET;
gadgets.io.makeRequest(url, function(response)
{
if (response.data && response.data.RedirectUrl)
HandleLogin(response.data.RedirectUrl);
else if(response.text)
{
showOneSection('main');
$('#main').append(response.text);
}
else
ShowDebug(response);
}, params);
The call does not reach my server. and when i try reaching the url in a browser it returns fast.
what can be the problem? how can i trouble shoot it?
Thanks
I finally found the problem.
when making a signed request you have to first obtain a consumer key + secret key.
see http://www.google.com/support/forum/p/apps-apis/thread?tid=31db71169fb6fc77&hl=en
you can do that here: https://www.google.com/gadgets/directory/verify
without the keys google is unable to sign the request (although one would expect a proper error message).