I am building a web app requiring access to a users gmail using Oauth2. I registered my app and can get the initial code, but can't figure out how to get an access token and refresh code afterwards.
First, the user is sent to a secure google page to put in user name/password. Afterwards, google redirects the user to something like:
127.0.0.1/oauth2callback?code=4/ux5gNj-_mIu4DOD_gNZdjX9E
I have this method below to handle the redirect. The code is sent with other info in a post request back to Google in exchange for a access token and refresh code. Unfortunately the response in the bottom has blank body. What am I doing wrong? Do I need to call another function on response to get the access token?
def oauth2callback
require "uri"
require "net/http"
uri = URI.parse("https://accounts.google.com/o/oauth2/token")
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Post.new(uri.request_uri)
request.set_form_data(
{'code'=>params[:code],
'client_id' => CLIENT_ID,
'client_secret' => CLIENT_SECRET,
'redirect_uri' => '127.0.0.1:3000/oauth2callback',
'grant_type' => 'authorization_code'})
http.use_ssl = true
response = http.request(request)
#response.body() is blank
end
Your redirect uri must match exactly the one, the user got redirected to. In your case this is 127.0.0.1/oauth2callback without :3000.
However, I believe that for Google both uri's needn't to be identical, but at least defined in the developer console, so maybe you could try adding 127.0.0.1:3000/oauth2callback to your developer console.
Related
sigining in with next_auth and a google provider sends me to the "site URL configuration" setting.
(the main site URL)
with an access token at the end of the URL.
Siging in on the same page with normal means works fine.
I am using the supabse "nextjs auth helpers"
I have everything working normally outside of google.
I have everything set up correctly according to the youtube videos and docs after checking over and over a few times.
after reaching the page:
https://accounts.google.com/o/oauth2/auth/oauthchooseaccount?
in which you choose your google account.
the redirect after goes to the redirect emails send you to, but does not have the person logged in.
I cant figure out why this is, the token should have been used to log in.
const [supabaseClient] = useState(() =>
createBrowserSupabaseClient(
process.env.NEXT_PUBLIC_SUPABASE_URL, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
)
has just been corrected to :
const [supabaseClient] = useState(() =>
createBrowserSupabaseClient({
supabaseUrl: process.env.NEXT_PUBLIC_SUPABASE_URL,
supabaseKey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
})
);
I'm trying to setup a manual flow for Facebook login, as per the docs at: https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/
I've got my test Facebook app working as expected, i.e., I can login using a private web browser window fine. The URL I'm using is:
https://facebook.com/v3.3/dialog/oauth?client_id=<app_id>&display=popup&response_type=token&redirect_uri=https://www.facebook.com/connect/login_success.html
Now within my React-Native app, I'm using react-native-inappbrowser-reborn to present a SFAuthenticationSession on iOS. As per their docs (at https://www.npmjs.com/package/react-native-inappbrowser-reborn), I'm doing the following:
const redirectUri = "https://www.facebook.com/connect/login_success.html"
const url = "https://facebook.com/v3.3/dialog/oauth?client_id="+appId+"&display=popup&response_type=token&redirect_uri=https://www.facebook.com/connect/login_success.html"
InAppBrowser.isAvailable()
.then(() => {
InAppBrowser.openAuth(url, redirectUri, {
// iOS Properties
dismissButtonStyle: 'cancel',
// Android Properties
showTitle: false,
enableUrlBarHiding: true,
enableDefaultShare: true,
})
.then((response) => {
// Only gets to this point if user explicitly cancels.
// So this does not trigger upon successful login.
})
// catch handlers follow
Using the above, my app correctly open up an in-app browser and I can login fine using a test user for my test app. Upon successful login though, I don't get redirected back to the .then completion handler. It just stays in the in-app browser view and I see the same message from Facebook that I see when logging in using a web browser. It says something like "Success. Please treat the url the same as you would a password", or something like that.
I may be missing something here, but I thought the purpose of passing redirectUri as an argument to openAuth was so that upon redirection to that URI, the completion handler would be triggered.
Question: How do I redirect back to the completion handler upon login success?
I think that you already have a solution but thought it might be useful for someone else facing this issue. If you don't have a solution so far follow my instructions:
You can't directly redirect back to your application using deep link, since Facebook will not call a link `like myapplicationname://mycustompath´. It's only possible to call links using the https-protocol (https://...).
The solution I'd suggest you to use is to redirect using your own API (Facebook -> Your API -> Deep Link Redirection). You will understand why this is required in the most of the real world applications at the end of the instructions.
Starting from your react-native app call the authorize endpoint of Facebook with a redirection to your application and set the global deeplink of your app as redirect uri.
InAppBrowser.close();
InAppBrowser.openAuth("https://graph.facebook.com/oauth/authorize?client_id=YOURCLIENTID&redirect_uri=https://YOURDOMAIN:PORT/auth/facebook", "{YOURAPPSDEEPLINKNAME}://{SOMEPATHYOUWANTTOEND}")
.then((response) => {
handleAuthorized(response, LOGINTYPE.FACEBOOK);
});
Now after login you'll be redirected to your API with the authorization code token as query parameter (e.g. https://YOURDOMAIN:PORT/auth/facebook?code=AVERYLONGCODESENTBYFACEBOOK)
Using this code token from the query parameter, you make another API Call to get the access_token for the user
{GET}: https://graph.facebook.com/v15.0/oauth/access_token?client_id=YOUR_CLIENT_ID&redirect_uri=https://YOURDOMAIN:PORT/auth/facebook&client_secret=YOUR_CLIENT_SECRET&code=AVERYLONGCODESENTBYFACEBOOK
Facebook's API will send you an answer as JSON with the access_token inside.
You can make another call using the access token of the user, to get the userId and the username
{GET}: https://graph.facebook.com/me?access_token=ACCESS_TOKEN_SENT_BY_FACEBOOK_IN_PREVIOUS_GET_REQUEST.
If you need the e-mail address for the user you have to make another call. Make sure you'd set the permission to read the e-mail address for your app on the developer portal of facebook.
The following request will return you the id, name and the email of the user
{GET}: https://graph.facebook.com/USERIDFROMPREVIOUSREQUEST?fields=id,name,email&access_token=ACCESSTOKEN
I think you want to save all these information to a database and create a session in order to keep the user logged in and therefore all the requests described will be useful for you in a real application.
After doing all the backend stuff, you're ready for the redirection using deep link. To do that, set a meta-tag to redirect the inappbrowser to your application:
<meta http-equiv="refresh" content="0; URL={YOURAPPSDEEPLINKNAME}://{SOMEPATHYOUWANTTOEND}" />
How do I ensure that a user is logged in before I render a view using loopback?
I can loggin in the front end using my angular app. But I wanted to block anonymous users from viewing the page.
I thought it would be a header, something like headers.authorization_token, but it does not seem to be there.
I am looking for something like connect-ensurelogin for passport, without having to use passport.
This is the $interceptor that solves your problem.
This code detects 401 responses (user not logged in or the access token is expired) from Loopback REST server and redirect the user to the login page:
// Inside app config block
$httpProvider.interceptors.push(function($q, $location) {
return {
responseError: function(rejection) {
if (rejection.status == 401) {
$location.nextAfterLogin = $location.path();
$location.path('/login');
}
return $q.reject(rejection);
}
};
});
And this code will redirect to the requested page once the user is logged in
// In the Login controller
User.login($scope.credentials, function() {
var next = $location.nextAfterLogin || '/';
$location.nextAfterLogin = null;
$location.path(next);
});
Here is one possible approach that has worked for me (details may vary):
Design each of the Pages in your Single Page Angular App to make at one of your REST API calls when the Angular Route is resolved.
Secure all of your REST API Routes using the AccessToken/User/Role/ACL scheme that LoopBack provides.
When no valid Access Token is detected on the REST Server side, pass back a 401 Unauthorized Error.
On the Client Side Data Access, when you detect a 401 on your REST Call, redirect to your Logic Route.
For the smoothest User Experience, whenever you redirect to Login, store the Route the User wanted to access globally
(localStore, $RootScope, etc.) and redirect back there when the User
Logs in and gets a valid Access Token.
Here is the LoopBack Access Control sample: https://github.com/strongloop/loopback-example-access-control
I have set up a servicestack service with basic authentication using the first example, here:
https://github.com/ServiceStack/ServiceStack/wiki/Authentication-and-authorization
This automatically sets up a route: /auth/basic
However, I cannot find any information or examples on how to format a request to this URL (Variables/GET/POST/Auth Header, etc.).
I am able to access a simple service using the basic authentication credentials, so they are active and correct.
I have no custom authentication plugged in, just basic authentication.
I have tried:
Using a JsonServiceClient to send UserName and Password variables by GET or Json POST to /auth/basic, with and without an Auth header also containing the user & pass.
Using a browser to send GET requests with URL parameters of the user/pass, or as http://user:pass#localhost:123/auth/basic
I always just get "HTTP/1.1 401 Invalid BasicAuth credentials".
The only examples I can find involve some kind of custom authentication, and then /auth/credentials is accessed, but I want to use /auth/basic
I have looked at the code and it looks like it reads an Auth header, but the service does not accept one.
I am actually trying to get this working so I can then disable it and verify it is disabled (I want to require basic authentication for every request).
Questions are:
What is the correct way to call the /auth/basic service? I will take a servicestack client API example, specifications or even a raw http request!
How do you disable the /auth services altogether?
Many thanks.
What is the correct way to call the /auth/basic service? I will take a servicestack client API example, specifications or even a raw http request!
var client = new JsonServiceClient("http://localhost:56006/api");
var resp = client.Post(new Auth() { UserName = "TestUser", Password = "Password" });
This assumes you have also registered an ICacheClient and IAuthUserRepository (and added a user account)
The JSON format looks like this if you call into /auth/basic?format=json
{
"UserName": "admin",
"Password": "test"
"RememberMe": true
}
How do you disable the /auth services altogether?
Don't add the AuthFeature plugin to configuration.
You can also remove plugins
Plugins.RemoveAll(x => x is AuthFeature);
Putting the following in apphost config seems to do the trick.
//Disable most things, including SOAP support, /auth and /metadata routes
SetConfig(new EndpointHostConfig()
{
EnableFeatures = Feature.Json | Feature.Xml
});
I am a little suspicious about what this does to /auth however, because it returns an empty response, while most routes return 404.
So, would this truly disable the /auth functionality? As in, if someone formed a correct request to /auth/credentials, will it still return an empty response?
I am new to using APIs of Websites. But since a long time I wanted to learn this and today started with the simple example of how to access information from soundcloud. Here is the code of the simple example from their website
require 'rubygems'
gem 'soundcloud-ruby-api-wrapper'
require 'soundcloud'
gem 'oauth'
require 'oauth'
# Create a Soundcloud OAuth consumer token object
sc_consumer = Soundcloud.consumer('YOUR_APPLICATION_CONSUMER_TOKEN','YOUR_APPLICATION_CONSUMER_SECRET')
# Create an OAuth access token object
access_token = OAuth::AccessToken.new(sc_consumer, 'YOUR_OAUTH_ACCESS_TOKEN', 'YOUR_OAUTH_ACCESS_SECRET')
# Create an authenticated Soundcloud client, based on the access token
sc_client = Soundcloud.register({:access_token => access_token})
# Get the logged in user
my_user = sc_client.User.find_me
# Display his full name
p "Hello, my name is #{my_user.full_name}"
I know what to set as:
'YOUR_APPLICATION_CONSUMER_TOKEN'
'YOUR_APPLICATION_CONSUMER_SECRET'
as this was given when registering a application on soundcloud.
I set the 'YOUR_OAUTH_ACCESS_TOKEN' to http://api.soundcloud.com/oauth/access_token
which was also written on the soundcloud site, but I have no idea where to get the
_YOUR_OAUTH_ACCESS_SECRET_ from.
Is this access secret also a random string that I get from somewhere, do I have to generate it by myself.
EDIT As suggested in the answer of the Elite Gentlemen I also tried the Soundcloud example on authentication. I post here the piece of code which already leads to the error:
require 'rubygems'
gem 'soundcloud-ruby-api-wrapper'
require 'soundcloud'
# oAuth setup code:
# Enter your consumer key and consumer secret values here:
#consumer_application = {:key => 'QrhxUWqgIswl8a9ESYw', :secret => 'tqsUGUD3PscK17G2KCQ4lRzilA2K5L5q2BFjArJzmjc'}
# Enter the path to your audio file here.
path_to_audio_file = "your/absolute/path/to/audio_file.ext"
# Set up an oAuth consumer.
#consumer = OAuth::Consumer.new #consumer_application[:key], #consumer_application[:secret],
{
:site => 'http://api.sandbox-soundcloud.com',
:request_token_path => '/oauth/request_token',
:access_token_path => '/oauth/access_token',
:authorize_path => '/oauth/authorize'
}
# Obtain an oAuth request token
puts "Get request token"
request_token = #consumer.get_request_token
The error message I receive then is:
OAuth::Unauthorized: 401 Unauthorized
method token_request in consumer.rb at
line 217 method get_request_token in
consumer.rb at line 139 at top
level in test1.rb at line 25
How can this simple example fail?
The answer to the question is very simple. My problem was that I had
registered my application on the soundcloud production system
soundcloud.com but directed my requests against sandbox-soundcloud.com.
I had to go to sandbox-soundcloud.com, register a new user account and make a
new client application and everything worked perfectly.
More information on the Sandbox is available here:
http://github.com/soundcloud/api/wiki/Appendix-B-Sandbox
As with OAuth, you will have to register your application with Soundcloud if you want the end-user to access Soundcloud's protected resources through your application.
When you request an access_token from Soundcloud using OAuth, it will return you and access_token and a oauth_token_secret. That oauth_token_secret is what you mentioned as YOUR_OAUTH_ACCESS_SECRET
I don't know how familiar you are with OAuth. The documentation can be found here.
Edit OAuth authorization scheme changed a while back, (e.g. getting an access token requires you to specify a oauth_verifier).
See the SoundCloud example on Authentication using the latest OAuth specification.