Easy authentication with OpenStreetMap over OAuth 2.0.
See also: https://wiki.openstreetmap.org/wiki/OAuth
Differences with github.com/osmlab/osm-auth
This fork features a fetch
wrapper and single page support.
All changes in this repo have been merged up stream
Try it out now at: https://dschep.github.io/osm-auth/
Or you can run the demo locally by cloning this project, then run:
$ npm install
$ npm run build
$ openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -sha256 -days 365 -nodes -subj '/CN=localhost'
$ npm start -- -S
This will start a local server on port 8080. Then open https://127.0.0.1:8080/
in a browser.
To install @dschep/osm-auth as a dependency in your project:
$ npm install --save @dschep/osm-auth
@dschep/osm-auth is distributed in CJS and ESM module formats for maxmimum compatibility. (Read more about Javascript module formats)
const osmAuth = require('@dschep/osm-auth').osmAuth; // CJS named import
// or
import { osmAuth } from '@dschep/osm-auth'; // ESM named import
You can also use @dschep/osm-auth directly in a web browser. A good way to do this is to fetch the ESM module from the skypack CDN, which can even deliver minified versions.
<script type="module">
import { osmAuth } from 'https://cdn.skypack.dev/@dschep/osm-auth';
// example here
</script>
This project is tested in supported node versions and modern browsers. We attempt to use JavaScript syntax that will work in legacy environments like ES5 or Internet Explorer, but offer no guarantee that it will work. If you're targeting an environment like this, you're probably already building your own bundle with something like Babel.
See: https://wiki.openstreetmap.org/wiki/OAuth#OAuth_2.0_2
Register a new OAuth2.0 application on openstreetmap.org:
- Go to your user page
- Click 'My Settings'
- Click 'OAuth 2 applications'
- At the bottom, 'Register new application'
- Fill in the form & submit
- Copy & Paste the client ID, secret, redirect URI and scope(s) into the osmAuth config object as below
👉 Important:
- Remember to copy the
client_secret
after setting up your application. It won't be available later. - The "Redirect URIs" are URIs that OSM is allowed to redirect the user back to. You can supply multiple Redirect URIs separated by spaces, and change them later.
- Redirect URIs must use
https
, except for127.0.0.1
, which may usehttp
var redirectPath = window.location.origin + window.location.pathname;
var auth = osmAuth.osmAuth({
client_id: "JWXSAzNp64sIRMStTnkhMRaMxSR964V4sFgn3KUZNTA",
client_secret: "6umOXfkZqH5CVUtv6iDqN7k8o7mKbQvTrHvbDQH36hs",
redirect_uri: redirectPath + "land.html",
scope: "read_prefs",
auto: true // show a login form if the user is not authenticated and you try to do a call
});
document.getElementById("authenticate").onclick = function () {
// Signed method call - since `auto` is true above, this will
// automatically start an authentication process if the user isn't
// authenticated yet.
auth.xhr({ method: "GET", path: "/api/0.6/user/details" },
function (err, result) {
// result is an XML DOM containing the user details
}
);
};
Requires land.html
to be accessible, or a page that does the same thing -
calls an auth complete function - to be available.
var redirectPath = window.location.origin + window.location.pathname;
var auth = osmAuth.osmAuth({
client_id: "JWXSAzNp64sIRMStTnkhMRaMxSR964V4sFgn3KUZNTA",
client_secret: "6umOXfkZqH5CVUtv6iDqN7k8o7mKbQvTrHvbDQH36hs",
redirect_uri: redirectPath,
scope: "read_prefs",
auto: true // show a login form if the user is not authenticated and you try to do a call
singlepage: true,
});
document.getElementById("authenticate").onclick = function () {
// Signed method call - since `auto` is true above, this will
// automatically start an authentication process if the user isn't
// authenticated yet.
auth.xhr({ method: "GET", path: "/api/0.6/user/details" },
function (err, result) {
// result is an XML DOM containing the user details
}
);
};
if (window.location.search.includes('code')) {
auth.authenticate(function() {
// Fully authed at this point
});
}
Constructs an osmAuth
instance.
At a minimum, options
must contain OAuth2 client ID, secret, redirect URI, and scope(s):
var redirectPath = window.location.origin + window.location.pathname;
{
client_id: "JWXSAzNp64sIRMStTnkhMRaMxSR964V4sFgn3KUZNTA",
client_secret: "6umOXfkZqH5CVUtv6iDqN7k8o7mKbQvTrHvbDQH36hs",
redirect_uri: redirectPath + "land.html",
scope: "read_prefs"
}
Additional options are:
access_token
- Can pre-authorize with an OAuth2 bearer token if you have oneurl
- A base url (default: "https://www.openstreetmap.org")auto
- Iftrue
, attempt to authenticate automatically when calling.xhr()
orfetch()
(default:false
)singlepage
- Iftrue
, use page redirection instead of a popup (default:false
)loading
- Function called when auth-related xhr calls startdone
- Function called when auth-related xhr calls end
Removes any stored authentication tokens (legacy OAuth1 tokens too)
Returns: self
Test whether the user is currently authenticated
Returns: true
if authenticated, false
if not
First logs out, then runs the authentiation flow, finally calls the callback.
Param: callback
An "errback"-style callback (err
, result
), called when complete
Returns: none
Tries to bring an existing authentication popup to the front.
Returns: true
on success or false
if there is no authentication popup or if it couldn't be brought to the front (e.g. because of cross-origin restrictions).
The authorization code is a temporary code that a client can exchange for an access token. If using this library in single-page mode, you'll need to call this once your application has an auth_code
and wants to get an access_token.
Param: auth_code
The OAuth2 auth_code
Param: callback
An "errback"-style callback (err
, result
), called when complete
Returns: none
A fetch
wrapper that does authenticated calls if the user has logged in.
See: https://developer.mozilla.org/en-US/docs/Web/API/fetch
Param: path
The URL path (e.g. "/api/0.6/user/details") (or full url, if options.prefix
=false
)
Param: options
:
options.method
Passed to fetch
(e.g. 'GET', 'POST')
options.prefix
If true
path contains a path, if false
path contains the full url
options.body
Passed to fetch
options.headers
optional Object
containing request headers
Return: Promise
that resolves to a Response
if authenticated, otherwise null
A XMLHttpRequest
wrapper that does authenticated calls if the user has logged in.
See: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
Param: options
:
options.method
Passed to xhr.open
(e.g. 'GET', 'POST')
options.prefix
If true
path contains a path, if false
path contains the full url
options.path
The URL path (e.g. "/api/0.6/user/details") (or full url, if prefix
=false
)
options.content
Passed to xhr.send
options.headers
optional Object
containing request headers
Param: callback
An "errback"-style callback (err
, result
), called when complete
Return: XMLHttpRequest
if authenticated, otherwise null
Creates the XMLHttpRequest set up with a header and response handling.
See: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
Param: method
Passed to xhr.open
(e.g. 'GET', 'POST')
Param: url
Passed to xhr.open
Param: access_token
The OAuth2 bearer token
Param: data
Passed to xhr.send
Param: headers
Object
containing request headers
Param: callback
An "errback"-style callback (err
, result
), called when complete
Return: XMLHttpRequest
Pre-authorize this object, if we already have the bearer token from the start.
Param: val
Object
containing access_token
property
Return: self
Options (getter / setter)
If passed with no arguments, just return the options
If passed an Object, set the options then attempt to pre-authorize
Param: val?
Object containing options
Return: current options
(if getting), or self
(if setting)