Tag: APIs

Apple declined to implement 16 Web APIs in Safari due to privacy concerns

Why? Fingerprinting. Rather than these APIs being used for what they are meant for, they end up being used for gross ad tech. As in, “hey, we don’t know exactly who you are, but wait, through a script we can tell your phone stopped being idle from 8:00 am to 8:13 am and were near the Bluetooth device JBL BATHROOM, so it’s probably dad taking his morning poop! Let’s show him some ads for nicer speakers and flannel shirts ASAP.”

I’ll pull the complete list here from Catalin Cimpanu’s article:

  • Web Bluetooth – Allows websites to connect to nearby Bluetooth LE devices.
  • Web MIDI API – Allows websites to enumerate, manipulate and access MIDI devices.
  • Magnetometer API – Allows websites to access data about the local magnetic field around a user, as detected by the device’s primary magnetometer sensor.
  • Web NFC API – Allows websites to communicate with NFC tags through a device’s NFC reader.
  • Device Memory API – Allows websites to receive the approximate amount of device memory in gigabytes.
  • Network Information API – Provides information about the connection a device is using to communicate with the network and provides a means for scripts to be notified if the connection type changes
  • Battery Status API – Allows websites to receive information about the battery status of the hosting device.
  • Web Bluetooth Scanning – Allows websites to scan for nearby Bluetooth LE devices.
  • Ambient Light Sensor – Lets websites get the current light level or illuminance of the ambient light around the hosting device via the device’s native sensors.
  • HDCP Policy Check extension for EME – Allows websites to check for HDCP policies, used in media streaming/playback.
  • Proximity Sensor – Allows websites to retrieve data about the distance between a device and an object, as measured by a proximity sensor.
  • WebHID – Allows websites to retrieve information about locally connected Human Interface Device (HID) devices.
  • Serial API – Allows websites to write and read data from serial interfaces, used by devices such as microcontrollers, 3D printers, and othes.
  • Web USB – Lets websites communicate with devices via USB (Universal Serial Bus).
  • Geolocation Sensor (background geolocation) – A more modern version of the older Geolocation API that lets websites access geolocation data.
  • User Idle Detection – Lets website know when a user is idle.

I’m of mixing feelings. I do like the idea of the web being a competitive platform for building any sort of app and sometimes fancy APIs like this open those doors.

Not to mention that some of these APIs are designed to do responsible things, like knowing connections speeds through the Network Information API and sending less data if you can, and the same for the Battery Status API.

This is all a similar situation to :visited in CSS. Have you ever noticed how there are some CSS declarations you can’t use on visited links? JavaScript APIs will even literally lie about the current styling of visited links to make links always appear unvisited. Because fingerprinting.

Direct Link to ArticlePermalink


The post Apple declined to implement 16 Web APIs in Safari due to privacy concerns appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

, , , , , ,

Tackling Authentication With Vue Using RESTful APIs

Authentication (logging in!) is a crucial part of many websites. Let’s look at how to go about it on a site using Vue, in the same way it can be done with any custom back end. Vue can’t actually do authentication all by itself, —we’ll need another service for that, so we’ll be using another service (Firebase) for that, but then integrating the whole experience in Vue.

Authentication works quite differently on Single Page Applications (SPAs) than it works on sites that reload every page. You don’t have to make an SPA with Vue, but we will in this tutorial. 

Here’s the plan. We’ll build a UI for users to log in and the submitted data will be sent to a server to check if the user exists. If yes, we’ll be sent a token. That’s very useful, because it’s going to be used throughout our site  tocheck if the user is still signed in. If no, the user can always sign up. In other words, it can be used in lots of conditional contexts. Beyond that, if we need any information from the server that requires been logged in, the token is sent to the server through the URL so that information can be only sent to logged in users.

The complete demo of this tutorial is posted on GitHub for those that who are comfortable reading through the code. The rest of us can follow through with the article. The starter file is also on GitHub so you can follow through as we code together. 

After downloading the repo, you’ll run npm install in your terminal. If you’re going to build this application completely on your own, you’ll have to install Vuex, Vue Router, and axios. We’ll also use Firebase for this project, so take a moment to set up a free account and create a new project in there.

After adding the project to Firebase, go to the authentication section, and set up a sign in method where we would be using the traditional email/password provider, that’ll be stored on our Firebase servers.

After that we’ll then go to the Firebase Auth REST API documentation to get our sign up and sign in API endpoints. We’ll need an API key to use those endpoints in our app and it can be found in the Firebase project settings.

Firebase offers authentication over the SDK, but we’re using the Auth API to demonstrate authentication over any custom back end server.

In our stater file, we have the sign up form below. We’re keeping things pretty simple here since we’re focusing on learning the concepts.

<template>   <div id="signup">     <div class="signup-form">       <form @submit.prevent="onSubmit">         <div class="input">           <label for="email">Mail</label>           <input              type="email"              id="email"              v-model="email">         </div>         <div class="input">           <label for="name">Your Name</label>           <input             type="text"             id="name"             v-model.number="name">         </div>         <div class="input">           <label for="password">Password</label>           <input             type="password"             id="password"             v-model="password">         </div>         <div class="submit">           <button type="submit">Submit</button>         </div>       </form>     </div>   </div> </template>

If we weren’t working with an SPA, we would naturally use axios to send our data inside the script tag like this:

axios.post('https://identitytoolkit.googleapis.com/v1/account   s:signUp?key=[API_KEY]', {     email: authData.email,     password: authData.password,     returnSecureToken: true   })   .then(res => {     console.log(res)   })   .catch(error => console.log(error))           } }

Sign up and log in

Working with an SPA (using Vue in this case) is very different from the above approach. Instead, we’ll be sending our authorization requests using Vuex in our actions in the store.js file. We’re doing it this way because we want the entire app to be aware of any change to the user’s authentication status.

actions: {   signup ({commit}, authData) {     axios.post('https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=[API_KEY]', {       email: authData.email,       password: authData.password,       returnSecureToken: true     })     .then(res => {       console.log(res)       router.push("/dashboard")     })     .catch(error => console.log(error))   },   login ({commit}, authData) {     axios.post(https://identitytoolkit.googleapis.com/v1/accounts:signIn?key=[API_KEY]', {       email: authData.email,       password: authData.password,       returnSecureToken: true     })     .then(res => {       console.log(res)       router.push("/dashboard")     })     .catch(error => console.log(error))   } }

We can use pretty much the same thing for the sign in method, but using the sign in API endpoint instead. We then dispatch both the sign up and log in from the components, to their respective actions in the store.

methods : {    onSubmit () {     const formData = {       email : this.email,       name : this.name,            password : this.password     }     this.$ store.dispatch('signup', formData)     }   } }

formData contains the user’s data.

methods : {   onSubmit () {     const formData = {       email : this.email,       password : this.password     }     this.$ store.dispatch('login', {email: formData.email, password: formData.password})   } }

We’re taking the authentication data (i.e. the token and the user’s ID) that was received from the sign up/log in form, and using them as state with Vuex. It’ll initially result as null.

state: {   idToken: null,   userId: null,   user: null }

We now create a new method called authUser in the mutations that’ll store the data that’s collected from the response. We need to import the router into the store as we’ll need that later.

import router from '/router' 
 mutations : {   authUser (state, userData) {     state.idToken = userData.token     state.userId = userData.userId   } }

Inside the .then block in the signup/login methods in our actions, we’ll commit our response to the authUser mutation just created and save to local storage.

actions: {   signup ({commit}, authData) {     axios.post('https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=[API_KEY]'), {       email: authData.email,       password: authData.password,       returnSecureToken: true     })     .then(res => {       console.log(res)       commit('authUser', {         token: res.data.idToken,         userId: res.data.localId       })       localStorage.setItem('token', res.data.idToken)       localStorage.setItem('userId', res.data.localId)       router.push("/dashboard")     })     .catch(error => console.log(error))   },   login ({commit}, authData) {     axios.post('https://identitytoolkit.googleapis.com/v1/accounts:signIn?key=[API_KEY]'), {       email: authData.email,       password: authData.password,       returnSecureToken: true     })     .then(res => {       console.log(res)       commit('authUser', {         token: res.data.idToken,         userId: res.data.localId       })         localStorage.setItem('token', res.data.idToken)         localStorage.setItem('userId', res.data.localId)         router.push("/dashboard")       })     .catch(error => console.log(error))   } }

Setting up an Auth guard

Now that we have our token stored within the application, we’re going touse this token while setting up our Auth guard. What’s an Auth guard? It protects the dashboard from unauthenticated users access it without tokens.

First, we’ll go into our route file and import the store. The store is imported because of the token that’ll determine the logged in state of the user.

import store from './store.js'

Then within our routes array, go to the dashboard path and add the method beforeEnter which takes three parameters: to, from and next. Within this method, we’re simply saying that if the tokens are stored (which is automatically done if authenticated), then next, meaning it continues with the designated route. Otherwise, we’re leading the unauthenticated user back to the sign up page.

{   path: '/dashboard',   component: DashboardPage,   beforeEnter (to, from, next) {     if (store.state.idToken) {       next()     }      else {       next('/signin')     }   } }

Creating the UI state

At this point, we can still see the dashboard in the navigation whether we’re logged in or not,  and that’s not what we want. We have to add another method under the getters called ifAuthenticated which checks if the token within our state is null, then update the navigation items accordingly.

getters: {   user (state) {     return state.user   },   ifAuthenticated (state) {     return state.idToken !== null   } }

Next, let’s open up the header component and create a method called auth inside the computed property. That will dispatch to the ifAuthenticated getters we just created in the store. ifAuthenticated will return false if there’s no token, which automatically means auth would also be null, and vice versa. After that, we add a v-if to check if auth is null or not, determining whether the dashboard option would show in the navigation.

<template>   <header id="header">     <div class="logo">       <router-link to="/">Vue Authenticate</router-link>     </div>     <nav>       <ul>         <li v-if='auth'>           <router-link to="/dashboard">Dashboard</router-link>         </li>         <li  v-if='!auth'>           <router-link to="/signup">Register</router-link>         </li>         <li  v-if='!auth'>           <router-link to="/signin">Log In</router-link>         </li>       </ul>     </nav>   </header> </template> <script>   export default {     computed: {       auth () {         return this.$ store.getters.ifAuthenticated       }     },   } </script>

Logging out

What’s an application without a logout button? Let’s create a new mutation called clearAuth, which sets both the token and userId to null.

mutations: {   authUser (state, userData) {     state.idToken = userData.token     state.userId = userData.userId   },   clearAuth (state) {     state.idToken = null     state.userId = null   } }

Then, in our logout action , we commit to clearAuth, delete local storage and add router.replace('/') to properly redirect the user following logout.

Back to the header component. We have an onLogout method that dispatches our logout action in the store. We then add a @click to the button which calls the to the onLogout method as we can see below:

<template>   <header id="header">     <div class="logo">       <router-link to="/">Vue Authenticate</router-link>     </div>     <nav>       <ul>         <li v-if='auth'>           <router-link to="/dashboard">Dashboard</router-link>         </li>         <li  v-if='!auth'>           <router-link to="/signup">Register</router-link>         </li>         <li  v-if='!auth'>           <router-link to="/signin">Log In</router-link>         </li>          <li  v-if='auth'>           <ul @click="onLogout">Log Out</ul>         </li>       </ul>     </nav>   </header> </template> <script>   export default {     computed: {       auth () {         return this.$ store.getters.ifAuthenticated       }     },     methods: {       onLogout() {         this.$ store.dispatch('logout')       }     }   } </script>

Auto login? Sure!

We’re almost done with our app. We can sign up, log in, and log out with all the UI changes we just made. But, when we refresh our app, we lose the data and are signed out, having to start all over again because we stored our token and Id in Vuex, which is JavaScript. This means everything in the app gets reloaded in the browser when refreshed. 

What we’ll do is to retrieve the token within our local storage. By doing that, we can have the user’s token in the browser regardless of when we refresh the window, and even auto-login the user as long as the token is still valid.

Create a new actions method called AutoLogin, where we’ll get the token and userId from the local storage, only if the user has one. Then we commit our data to the authUser method in the mutations.

actions : {   AutoLogin ({commit}) {     const token = localStorage.getItem('token')     if (!token) {       return     }     const userId = localStorage.getItem('userId')     const token = localStorage.getItem('token')     commit('authUser', {       idToken: token,       userId: userId     })   } }

We then go to our App.vue and make a created method where we’ll dispatch the autoLogin from our store when the app is loaded.

created () {   this.$ store.dispatch('AutoLogin') }

Yay! With that, we’ve successfully implemented authentication within our app and can now deploy using npm run build. Check out the live demo to see it in action.

The example site is purely for demonstration purposes. Please do not share real data, like your real email and password, while testing the demo app.

The post Tackling Authentication With Vue Using RESTful APIs appeared first on CSS-Tricks.

CSS-Tricks

, , , ,
[Top]

APIs and Authentication on the Jamstack

The first “A” in the Jamstack stands for “APIs” and is a key contributor to what makes working with static sites so powerful. APIs give developers the freedom to offload complexity and provide avenues for including dynamic functionality to an otherwise static site. Often, accessing an API requires validating the authenticity of a request. This frequently manifests in the form of authentication (auth) and can be done either client side or server side depending on the service used and the task being accomplished. 

Given the vast spectrum of protocols available, APIs differ in their individual auth implementations. These auth protocols and implementation intricacies add an additional challenge when integrating APIs into a Jamstack site. Thankfully, there is a method to this madness. Every protocol can be mapped to a specific use case and implementing auth is a matter of understanding this.

To illustrate this best, let’s dive into the various protocols and the scenarios that they’re best suited for.

Summon the protocols

OAuth 2.0 is the general standard by which authentication today follows. OAuth is a fairly flexible authorization framework that constitutes a series of grants defining the relationship between a client and an API endpoint. In an OAuth flow, a client application requests an access token from an authorization endpoint and uses that to sign a request to an API endpoint.

There are four main grant types — authorization code, implicit flow, resource owner credential, and client credentials. We’ll look at each one individually.

Authorization Code Grant 

Of all OAuth grant types, the Authorization Code Grant is likely the most common one. Primarily used to obtain an access token to authorize API requests after a user explicitly grants permission, this grant flow follows a two-step process.

  • First, the user is directed to a consent screen aka the authorization server where they grant the service restricted access to their personal account and data.
  • Once permission has been granted, the next step is to retrieve an access token from the authentication server which can then be used to authenticate the request to the API endpoint.

Compared to other grant types, the Authorization Code Grant has an extra layer of security with the added step of asking a user for explicit authorization. This multi-step code exchange means that the access token is never exposed and is always sent via a secure backchannel between an application and auth server. In this way, attackers can’t easily steal an access token by intercepting a request. Google-owned services, like Gmail and Google Calendar, utilize this authorization code flow to access personal content from a user’s account. If you’d like to dig into this workflow more, check out this blog post to learn more.

Implicit Grant

The Implicit Grant is akin to the Authorization Code Grant with a noticeable difference: instead of having a user grant permission to retrieve an authorization code that is then exchanged for an access token, an access token is returned immediately via the the fragment (hash) part of the redirect URL (a.k.a. the front channel).

With the reduced step of an authorization code, the Implicit Grant flow carries the risk of exposing tokens. The token, by virtue of being embedded directly into the URL (and logged to the browser history), is easily accessible if the redirect is ever intercepted.

Despite its vulnerabilities, the Implicit Grant can be useful for user-agent-based clients like Single Page Applications. Since both application code and storage is easily accessed in client-side rendered applications, there is no safe way to keep client secrets secure. The implicit flow is the logical workaround to this by providing applications a quick and easy way to authenticate a user on the client side. It is also a valid means to navigate CORS issues, especially when using a third-party auth server that doesn’t support cross-origin requests. Because of the inherent risks of exposed tokens with this approach, it’s important to note that access tokens in Implicit Flow tend to be short-lived and refresh tokens are never issued. As a result, this flow may require logging in for every request to a privileged resource.

Resource Owner Credential

In the case of the Resource Owner Credential Grant, resource owners send their username and password credentials to the auth server, which then sends back an access token with an optional refresh token. Since resource owner credentials are visible in the auth exchange between client application and authorization server, a trust relationship must exist between resource owner and client application. Though evidently less secure than other grant types, the Resource Owner Credential grant yields an excellent user experience for first party clients. This grant flow is most suitable in cases where the application is highly privileged or when working within a device’s operating system. This authorization flow is often used when other flows are not viable.

Client Credential

The Client Credentials Grant type is used primarily when clients need to obtain an access token outside of the context of a user. This is suitable for machine to machine authentication when a user’s explicit permission cannot be guaranteed for every access to a protected resource. CLIs, and services running in the back end are instances when this grant type comes in handy. Instead of relying on user login, a Client ID and Secret are passed along to obtain a token which can then be used to authenticate an API request.

Typically, in the Client Credential grant, a service account is established through which the application operates and makes API calls. This way, users are not directly involved and applications can still continue to authenticate requests. This workflow is fairly common in situations where applications want access to their own data, e.g. Analytics, rather than to specific user data.

Conclusion

With its reliance on third party services for complex functionality, a well-architected authentication solution is crucial to maintain the security of Jamstack sites. APIs, being the predominant way to exchange data in the Jamstack, are a big part of that. We looked at four different methods for authenticating API requests, each with its benefits and impacts on user experience.

We mentioned at the start that these four are the main forms of authentication that are used to request data from an API. There are plenty of other types as well, which are nicely outlined on oauth.net. The website as a whole is an excellent deep-dive on not only the auth types available, but the OAuth framework as a whole.

Do you prefer one method over another? Do you have an example in use you can point to? Share in the comments!

The post APIs and Authentication on the Jamstack appeared first on CSS-Tricks.

CSS-Tricks

, ,
[Top]

Get Started Building GraphQL APIs With Node

We all have a number of interests and passions. For example, I’m interested in JavaScript, 90’s indie rock and hip hop, obscure jazz, the city of Pittsburgh, pizza, coffee, and movies starring John Lurie. We also have family members, friends, acquaintances, classmates, and colleagues who also have their own social relationships, interests, and passions. Some of these relationships and interests overlap, like my friend Riley who shares my interest in 90’s hip hop and pizza. Others do not, like my colleague Harrison, who prefers Python to JavaScript, only drinks tea, and prefers current pop music. All together, we each have a connected graph of the people in our lives, and the ways that our relationships and interests overlap.

These types of interconnected data are exactly the challenge that GraphQL initially set out to solve in API development. By writing a GraphQL API we are able to efficiently connect data, which reduces the complexity and number of requests, while allowing us to serve the client precisely the data that it needs. (If you’re into more GraphQL metaphors, check out Meeting GraphQL at a Cocktail Mixer.)

In this article, we’ll build a GraphQL API in Node.js, using the Apollo Server package. To do so, we’ll explore fundamental GraphQL topics, write a GraphQL schema, develop code to resolve our schema functions, and access our API using the GraphQL Playground user interface.

What is GraphQL?

GraphQL is an open source query and data manipulation language for APIs. It was developed with the goal of providing single endpoints for data, allowing applications to request exactly the data that is needed. This has the benefit of not only simplifying our UI code, but also improving performance by limiting the amount of data that needs to be sent over the wire.

What we’re building

To follow along with this tutorial, you’ll need Node v8.x or later and some familiarity with working with the command line. 

We’re going to build an API application for book highlights, allowing us to store memorable passages from the things that we read. Users of the API will be able to perform “CRUD” (create, read, update, delete) operations against their highlights:

  • Create a new highlight
  • Read an individual highlight as well as a list of highlights
  • Update a highlight’s content
  • Delete a highlight

Getting started

To get started, first create a new directory for our project, initialize a new node project, and install the dependencies that we’ll need:

# make the new directory mkdir highlights-api # change into the directory cd highlights-api # initiate a new node project npm init -y # install the project dependencies npm install apollo-server graphql # install the development dependencies npm install nodemon --save-dev

Before moving on, let’s break down our dependencies:

  • apollo-server is a library that enables us to work with GraphQL within our Node application. We’ll be using it as a standalone library, but the team at Apollo has also created middleware for working with existing Node web applications in ExpresshapiFastify, and Koa.
  • graphql includes the GraphQL language and is a required peer dependency of apollo-server.
  • nodemon is a helpful library that will watch our project for changes and automatically restart our server.

With our packages installed, let’s next create our application’s root file, named index.js. For now, we’ll console.log() a message in this file:

console.log("📚 Hello Highlights");

To make our development process simpler, we’ll update the scripts object within our package.json file to make use of the nodemon package:

"scripts": {   "start": "nodemon index.js" },

Now, we can start our application by typing npm start in the terminal application. If everything is working properly, you will see 📚 Hello Highlights logged to your terminal.

GraphQL schema types

A schema is a written representation of our data and interactions. By requiring a schema, GraphQL enforces a strict plan for our API. This is because the API can only return data and perform interactions that are defined within the schema. The fundamental component of GraphQL schemas are object types. GraphQL contains five built-in types:

  • String: A string with UTF-8 character encoding
  • Boolean: A true or false value
  • Int: A 32-bit integer
  • Float: A floating-point value
  • ID: A unique identifier

We can construct a schema for an API with these basic components. In a file named schema.js, we can import the gql library and prepare the file for our schema syntax:

const { gql } = require('apollo-server');  const typeDefs = gql`   # The schema will go here `;  module.exports = typeDefs;

To write our schema, we first define the type. Let’s consider how we might define a schema for our highlights application. To begin, we would create a new type with a name of Highlight:

const typeDefs = gql`   type Highlight {   } `;

Each highlight will have a unique ID,  some content, a title, and an author. The Highlight schema will look something like this:

const typeDefs = gql`   type Highlight {     id: ID     content: String     title: String     author: String   } `;

We can make some of these fields required by adding an exclamation point:

const typeDefs = gql`   type Highlight {     id: ID!     content: String!     title: String     author: String   } `;

Though we’ve defined an object type for our highlights, we also need to provide a description of how a client will fetch that data. This is called a query. We’ll dive more into queries shortly, but for now let’s describe in our schema the ways in which someone will retrieve highlights. When requesting all of our highlights, the data will be returned as an array (represented as [Highlight]) and when we want to retrieve a single highlight we will need to pass an ID as a parameter.

const typeDefs = gql`   type Highlight {     id: ID!     content: String!     title: String     author: String   }   type Query {     highlights: [Highlight]!     highlight(id: ID!): Highlight   } `;

Now, in the index.js file, we can import our type definitions and set up Apollo Server:

const {ApolloServer } = require('apollo-server'); const typeDefs = require('./schema');  const server = new ApolloServer({ typeDefs });  server.listen().then(({ url }) => {   console.log(`📚 Highlights server ready at $ https://css-tricks.com/get-started-building-graphql-apis-with-node/`); });

If we’ve kept the node process running, the application will have automatically updated and relaunched, but if not, typing npm start  from the project’s directory in the terminal window will start the server. If we look at the terminal, we should see that nodemon is watching our files and the server is running on a local port:

[nodemon] 2.0.2 [nodemon] to restart at any time, enter `rs` [nodemon] watching dir(s): *.* [nodemon] watching extensions: js,mjs,json [nodemon] starting `node index.js` 📚 Highlights server ready at http://localhost:4000/

Visiting the URL in the browser will launch the GraphQL Playground application, which provides a user interface for interacting with our API.

GraphQL Resolvers

Though we’ve developed our project with an initial schema and Apollo Server setup, we can’t yet interact with our API. To do so, we’ll introduce resolvers. Resolvers perform exactly the action their name implies; they resolve the data that the API user has requested. We will write these resolvers by first defining them in our schema and then implementing the logic within our JavaScript code. Our API will contain two types of resolvers: queries and mutations.

Let’s first add some data to interact with. In an application, this would typically be data that we’re retrieving and writing to from a database, but for our example let’s use an array of objects. In the index.js file add the following:

let highlights = [   {     id: '1',     content: 'One day I will find the right words, and they will be simple.',     title: 'Dharma Bums',     author: 'Jack Kerouac'   },   {     id: '2',     content: 'In the limits of a situation there is humor, there is grace, and everything else.',     title: 'Arbitrary Stupid Goal',     author: 'Tamara Shopsin'   } ]

Queries

A query requests specific data from an API, in its desired format. The query will then return an object, containing the data that the API user has requested. A query never modifies the data; it only accesses it. We’ve already written a two queries in our schema. The first returns an array of highlights and the second returns a specific highlight. The next step is to write the resolvers that will return the data.

In the index.js file, we can add a resolvers object, which can contain our queries:

const resolvers = {   Query: {     highlights: () => highlights,     highlight: (parent, args) => {       return highlights.find(highlight => highlight.id === args.id);     }   } };

The highlights query returns the full array of highlights data. The highlight query accepts two parameters: parent and args. The parent is the first parameter of any GraqhQL query in Apollo Server and provides a way of accessing the context of the query. The args parameter allows us to access the user provided arguments. In this case, users of the API will be supplying an id argument to access a specific highlight.

We can then update our Apollo Server configuration to include the resolvers:

const server = new ApolloServer({ typeDefs, resolvers });

With our query resolvers written and Apollo Server updated, we can now query API using the GraphQL Playground. To access the GraphQL Playground, visit http://localhost:4000 in your web browser.

A query is formatted as so:

query {   queryName {       field       field     } }

With this in mind, we can write a query that requests the ID, content, title, and author for each our highlights:

query {   highlights {     id     content     title     author   } }

Let’s say that we had a page in our UI that lists only the titles and authors of our highlighted texts. We wouldn’t need to retrieve the content for each of those highlights. Instead, we could write a query that only requests the data that we need:

query {   highlights {     title     author   } }

We’ve also written a resolver to query for an individual note by including an ID parameter with our query. We can do so as follows:

query {   highlight(id: "1") {     content   } }

Mutations

We use a mutation when we want to modify the data in our API. In our highlight example, we will want to write a mutation to create a new highlight, one to update an existing highlight, and a third to delete a highlight. Similar to a query, a mutation is also expected to return a result in the form of an object, typically the end result of the performed action.

The first step to updating anything in GraphQL is to write the schema. We can include mutations in our schema, by adding a mutation type to our schema.js file:

type Mutation {   newHighlight (content: String! title: String author: String): Highlight!   updateHighlight(id: ID! content: String!): Highlight!   deleteHighlight(id: ID!): Highlight! }

Our newHighlight mutation will take the required value of content along with optional title and author values and return a Highlight. The updateHighlight mutation will require that a highlight id and content be passed as argument values and will return the updated Highlight. Finally, the deleteHighlight mutation will accept an ID argument, and will return the deleted Highlight.

With the schema updated to include mutations, we can now update the resolvers in our index.js file to perform these actions. Each mutation will update our highlights array of data.

const resolvers = {   Query: {     highlights: () => highlights,     highlight: (parent, args) => {       return highlights.find(highlight => highlight.id === args.id);     }   },   Mutation: {     newHighlight: (parent, args) => {       const highlight = {         id: String(highlights.length + 1),         title: args.title || '',         author: args.author || '',         content: args.content       };       highlights.push(highlight);       return highlight;     },     updateHighlight: (parent, args) => {       const index = highlights.findIndex(highlight => highlight.id === args.id);       const highlight = {         id: args.id,         content: args.content,         author: highlights[index].author,         title: highlights[index].title       };       highlights[index] = highlight;       return highlight;     },     deleteHighlight: (parent, args) => {       const deletedHighlight = highlights.find(         highlight => highlight.id === args.id       );       highlights = highlights.filter(highlight => highlight.id !== args.id);       return deletedHighlight;     }   } };

With these mutations written, we can use the GraphQL Playground to practice mutating the data. The structure of a mutation is nearly identical to that of a query, specifying the name of the mutation, passing the argument values, and requesting specific data in return. Let’s start by adding a new highlight:

mutation {   newHighlight(author: "Adam Scott" title: "JS Everywhere" content: "GraphQL is awesome") {     id     author     title     content   } }

We can then write mutations to update a highlight:

mutation {   updateHighlight(id: "3" content: "GraphQL is rad") {     id     content   } }

And to delete a highlight:

mutation {   deleteHighlight(id: "3") {     id   } }

Wrapping up

Congratulations! You’ve now successfully built a GraphQL API, using Apollo Server, and can run GraphQL queries and mutations against an in-memory data object. We’ve established a solid foundation for exploring the world of GraphQL API development.

Here are some potential next steps to level up:

The post Get Started Building GraphQL APIs With Node appeared first on CSS-Tricks.

CSS-Tricks

, , , ,
[Top]

Design APIs: The Evolution of Design Systems

A clever idea from Matthew Ström:

[…] design APIs don’t seem like a stretch of the imagination. An API-driven approach is the natural extension of the work currently being done on design systems, including tokens and standardization projects.

If you buy into the idea of design tokens, that expresses itself as a chunk of JSON with things like colors and spacing values. No reason an API couldn’t deliver that, potentially empowering a build process that pulls the most recent decisions from a central location.

Direct Link to ArticlePermalink

The post Design APIs: The Evolution of Design Systems appeared first on CSS-Tricks.

CSS-Tricks

, , ,
[Top]

Spam Detection APIs

I was trying to research the landscape of these the other day — And by research, I mean light Googling and asking on Twitter. Weirdly, very little comes to mind when thinking about spam detection APIs. I mean some kind of URL endpoint, paid or not, where you can hit it with a block of text and whatever metadata it wants and it’ll tell you if it’s spam or not. Seems like something an absolute buttload of the internet could use and something companies of any size could monetize or offer free to show off their smart computer machines.

Akismet is the big kid on the block.

You might think of Akismet as a WordPress thing, and it is. It’s an Automattic product and is perhaps primarily used as a WordPress plugin. I run that here on CSS-Tricks and it’s blocked 1,989,326 so far.

It also has a generic API. There are libraries for Dart, JavaScript, PHP, Python, Ruby, Go, etc, as well as plugins for other CMSs. So if you use a different CMS or have your custom app, you can still use Akismet for spam detection.

After you get an API key, you can POST to a URL endpoint with all the data it needs and it’ll respond true if it’s spam or false if it’s not.

To get better results over time, you can also submit content telling it if it’s spam or ham (ham is the opposite of spam… good content).

Plino

Several folks mentioned Plino to me.

There is a lot to like here, like the fact that it’s free and returns a JSON response like you might be used to in development. There is the fancy buzzword “Machine Learning” being used here, too. It makes me think that with lots of people using this, it’ll get smarter and smarter as it goes. But there is no way to submit ham/spam, so I’m not sure that’s really the case.

There is other stuff that makes me nervous. It’s clearly on Heroku which is kinda expensive at scale, and so with no pricing model it seems like it could go away anytime. Sorta feels like a fun-but-abandoned side project. Last commit was two years ago, as I write.

OOPSpam

OOPSpam looks super similar to Plino, but has a pricing model, which is nice. They publish their latency, which is over two seconds. I haven’t compared that to the others so I have no idea if they are all that slow. Two seconds seems like a lot for an API call to me, but maybe it’s not that big of a deal since it’s an async submit?

CleanTalk

CleanTalk has a clear pricing structure and appears to have plenty of customers, which is a plus to me. The website looks a little janky though, which makes me worry a little.

(Sorry if that’s a little rude, but it’s just mental math to me. Good design is one of the least expensive investments a company can make to increase trust, so companies that overlook it make me wonder.)

It looks like they have a variety of anti-spam solutions though, which is interesting. For example, you can ask an API to see if an IP, email, or domain is on a blacklist, which is a pretty raw way of blocking bad stuff, but useful for stuff like protecting against spam registrations (rather than just checking blocks of text). They also have a firewall solution, which is interesting for folks trying to block spam before it even touches their servers.

Email options…

There are a couple out there that seem rather specific to testing emails. As in, testing your own emails before you send them to make sure they aren’t considered spam by email services. Here are a couple I cam across while looking around:

The post Spam Detection APIs appeared first on CSS-Tricks.

CSS-Tricks

, ,
[Top]

Earth day, API’s and sunshine.

Cassie Evans showcases some really nifty web design ideas and explores using the API provided by the company her team over at Clearleft recently hired to cover their building’s roof with solar panels. Cassie outlines her journey designing a webpage that uses the API to populate some light data visualizations about the energy the building uses now that the solar panels are installed.

Here at Clearleft we’ve been taking small steps to reduce our environmental impact. In December 2018 we covered the roof of our home with solar panels.

With the first of the glorious summer sun starting to shine down on us, we started to ponder about what environmental impact they’d had over the last 5 months.

Luckily for us, our solar panels have an API, so we can not only find out that information, we can request it from SolarEdge and display it in our very own interface.

The post is a great practical look into using the Fetch API which is also something Zell Liew wrote up in thorough detail, covering the history of using APIs with JavaScript, handling errors and other weird things that might happen when working with it.

But, equally interesting and useful is reading through Cassie’s thought process as she sketches a wireframe for the page, researches how to use the Fetch API, and integrates animation into a lovely SVG illustration. It’s an exercise in both design and development that many of us can relate to but also learn from.

Oh and while we’re on the topic of data visualizations, Dan Englishby posted something just today on the many ways if getting data into charts. Working with real-time APIs is covered there as well, and is a nice segue from Cassie’s post.

Direct Link to ArticlePermalink

The post Earth day, API’s and sunshine. appeared first on CSS-Tricks.

CSS-Tricks

, ,
[Top]

7 things you should know when getting started with Serverless APIs

I want you to take a second and think about Twitter, and think about it in terms of scale. Twitter has 326 million users. Collectively, we create ~6,000 tweets every second. Every minute, that’s 360,000 tweets created. That sums up to nearly 200 billion tweets a year. Now, what if the creators of Twitter had been paralyzed by how to scale and they didn’t even begin?

That’s me on every single startup idea I’ve ever had, which is why I love serverless so much: it handles the issues of scaling leaving me to build the next Twitter!

Live metrics with Application Insights

As you can see in the above, we scaled from one to seven servers in a matter of seconds, as more user requests come in. You can scale that easily, too.

So let’s build an API that will scale instantly as more and more users come in and our workload increases. We’re going to do that is by answering the following questions:


How do I create a new serverless project?

With every new technology, we need to figure out what tools are available for us and how we can integrate them into our existing tool set. When getting started with serverless, we have a few options to consider.

First, we can use the good old browser to create, write and test functions. It’s powerful, and it enables us to code wherever we are; all we need is a computer and a browser running. The browser is a good starting point for writing our very first serverless function.

Serverless in the browser

Next, as you get more accustomed to the new concepts and become more productive, you might want to use your local environment to continue with your development. Typically you’ll want support for a few things:

  • Writing code in your editor of choice
  • Tools that do the heavy lifting and generate the boilerplate code for you
  • Run and debug code locally
  • Support for quickly deploying your code

Microsoft is my employer and I’ve mostly built serverless applications using Azure Functions so for the rest of this article I’ll continue using them as an example. With Azure Functions, you’ll have support for all these features when working with the Azure Functions Core Tools which you can install from npm.

npm install -g azure-functions-core-tools

Next, we can initialize a new project and create new functions using the interactive CLI:

func CLI

If your editor of choice happens to be VS Code, then you can use it to write serverless code too. There’s actually a great extension for it.

Once installed, a new icon will be added to the left-hand sidebar — this is where we can access all our Azure-related extensions! All related functions can to be grouped under the same project (also known as a function app). This is like a folder for grouping functions that should scale together and that we want to manage and monitor at the same time. To initialize a new project using VS Code, click on the Azure icon and then the folder icon.

Create new Azure Functions project

This will generate a few files that help us with global settings. Let’s go over those now.

host.json

We can configure global options for all functions in the project directly in the host.json file.

In it, our function app is configured to use the latest version of the serverless runtime (currently 2.0). We also configure functions to timeout after ten minutes by setting the functionTimeout property to 00:10:00 — the default value for that is currently five minutes (00:05:00).

In some cases, we might want to control the route prefix for our URLs or even tweak settings, like the number of concurrent requests. Azure Functions even allows us to customize other features like logging, healthMonitor and different types of extensions.

Here’s an example of how I’ve configured the file:

// host.json {   "version": "2.0",   "functionTimeout": "00:10:00",   "extensions": {   "http": {     "routePrefix": "tacos",     "maxOutstandingRequests": 200,     "maxConcurrentRequests": 100,     "dynamicThrottlesEnabled": true   } } }

Application settings

Application settings are global settings for managing runtime, language and version, connection strings, read/write access, and ZIP deployment, among others. Some are settings that are required by the platform, like FUNCTIONS_WORKER_RUNTIME, but we can also define custom settings that we’ll use in our application code, like DB_CONN which we can use to connect to a database instance.

While developing locally, we define these settings in a file named local.settings.json and we access them like any other environment variable.

Again, here’s an example snippet that connects these points:

// local.settings.json {   "IsEncrypted": false,   "Values": {     "AzureWebJobsStorage": "your_key_here",     "FUNCTIONS_WORKER_RUNTIME": "node",     "WEBSITE_NODE_DEFAULT_VERSION": "8.11.1",     "FUNCTIONS_EXTENSION_VERSION": "~2",     "APPINSIGHTS_INSTRUMENTATIONKEY": "your_key_here",     "DB_CONN": "your_key_here",   } }

Azure Functions Proxies

Azure Functions Proxies are implemented in the proxies.json file, and they enable us to expose multiple function apps under the same API, as well as modify requests and responses. In the code below we’re publishing two different endpoints under the same URL.

// proxies.json {   "$ schema": "http://json.schemastore.org/proxies",   "proxies": {     "read-recipes": {         "matchCondition": {         "methods": ["POST"],         "route": "/api/recipes"       },       "backendUri": "https://tacofancy.azurewebsites.net/api/recipes"     },     "subscribe": {       "matchCondition": {         "methods": ["POST"],         "route": "/api/subscribe"       },       "backendUri": "https://tacofancy-users.azurewebsites.net/api/subscriptions"     }   } }

Create a new function by clicking the thunder icon in the extension.

Create a new Azure Function

The extension will use predefined templates to generate code, based on the selections we made — language, function type, and authorization level.

We use function.json to configure what type of events our function listens to and optionally to bind to specific data sources. Our code runs in response to specific triggers which can be of type HTTP when we react to HTTP requests — when we run code in response to a file being uploaded to a storage account. Other commonly used triggers can be of type queue, to process a message uploaded on a queue or time triggers to run code at specified time intervals. Function bindings are used to read and write data to data sources or services like databases or send emails.

Here, we can see that our function is listening to HTTP requests and we get access to the actual request through the object named req.

// function.json {   "disabled": false,   "bindings": [     {       "authLevel": "anonymous",       "type": "httpTrigger",       "direction": "in",       "name": "req",       "methods": ["get"],       "route": "recipes"     },     {       "type": "http",       "direction": "out",       "name": "res"     }   ] }

index.js is where we implement the code for our function. We have access to the context object, which we use to communicate to the serverless runtime. We can do things like log information, set the response for our function as well as read and write data from the bindings object. Sometimes, our function app will have multiple functions that depend on the same code (i.e. database connections) and it’s good practice to extract that code into a separate file to reduce code duplication.

//Index.js module.exports = async function (context, req) {   context.log('JavaScript HTTP trigger function processed a request.');    if (req.query.name || (req.body && req.body.name)) {       context.res = {           // status: 200, /* Defaults to 200 */           body: "Hello " + (req.query.name || req.body.name)       };   }   else {       context.res = {           status: 400,           body: "Please pass a name on the query string or in the request body"       };   } };

Who’s excited to give this a run?

How do I run and debug Serverless functions locally?

When using VS Code, the Azure Functions extension gives us a lot of the setup that we need to run and debug serverless functions locally. When we created a new project using it, a .vscode folder was automatically created for us, and this is where all the debugging configuration is contained. To debug our new function, we can use the Command Palette (Ctrl+Shift+P) by filtering on Debug: Select and Start Debugging, or typing debug.

Debugging Serverless Functions

One of the reasons why this is possible is because the Azure Functions runtime is open-source and installed locally on our machine when installing the azure-core-tools package.

How do I install dependencies?

Chances are you already know the answer to this, if you’ve worked with Node.js. Like in any other Node.js project, we first need to create a package.json file in the root folder of the project. That can done by running npm init -y — the -y will initialize the file with default configuration.

Then we install dependencies using npm as we would normally do in any other project. For this project, let’s go ahead and install the MongoDB package from npm by running:

npm i mongodb

The package will now be available to import in all the functions in the function app.

How do I connect to third-party services?

Serverless functions are quite powerful, enabling us to write custom code that reacts to events. But code on its own doesn’t help much when building complex applications. The real power comes from easy integration with third-party services and tools.

So, how do we connect and read data from a database? Using the MongoDB client, we’ll read data from an Azure Cosmos DB instance I have created in Azure, but you can do this with any other MongoDB database.

//Index.js const MongoClient = require('mongodb').MongoClient;  // Initialize authentication details required for database connection const auth = {   user: process.env.user,   password: process.env.password };  // Initialize global variable to store database connection for reuse in future calls let db = null; const loadDB = async () => {   // If database client exists, reuse it     if (db) {     return db;   }   // Otherwise, create new connection     const client = await MongoClient.connect(     process.env.url,     {       auth: auth     }   );   // Select tacos database   db = client.db('tacos');   return db; };  module.exports = async function(context, req) {   try {     // Get database connection     const database = await loadDB();     // Retrieve all items in the Recipes collection      let recipes = await database       .collection('Recipes')       .find()       .toArray();     // Return a JSON object with the array of recipes      context.res = {       body: { items: recipes }     };   } catch (error) {     context.log(`Error code: $ {error.code} message: $ {error.message}`);     // Return an error message and Internal Server Error status code     context.res = {       status: 500,       body: { message: 'An error has occurred, please try again later.' }     };   } };

One thing to note here is that we’re reusing our database connection rather than creating a new one for each subsequent call to our function. This shaves off ~300ms of every subsequent function call. I call that a win!

Where can I save connection strings?

When developing locally, we can store our environment variables, connection strings, and really anything that’s secret into the local.settings.json file, then access it all in the usual manner, using process.env.yourVariableName.

local.settings.json {   "IsEncrypted": false,   "Values": {     "AzureWebJobsStorage": "",     "FUNCTIONS_WORKER_RUNTIME": "node",     "user": "your-db-user",     "password": "your-db-password",     "url": "mongodb://your-db-user.documents.azure.com:10255/?ssl=true"   } }

In production, we can configure the application settings on the function’s page in the Azure portal.

However, another neat way to do this is through the VS Code extension. Without leaving your IDE, we can add new settings, delete existing ones or upload/download them to the cloud.

Debugging Serverless Functions

How do I customize the URL path?

With the REST API, there are a couple of best practices around the format of the URL itself. The one I settled on for our Recipes API is:

  • GET /recipes: Retrieves a list of recipes
  • GET /recipes/1: Retrieves a specific recipe
  • POST /recipes: Creates a new recipe
  • PUT /recipes/1: Updates recipe with ID 1
  • DELETE /recipes/1: Deletes recipe with ID 1

The URL that is made available by default when creating a new function is of the form http://host:port/api/function-name. To customize the URL path and the method that we listen to, we need to configure them in our function.json file:

// function.json {   "disabled": false,   "bindings": [     {       "authLevel": "anonymous",       "type": "httpTrigger",       "direction": "in",       "name": "req",       "methods": ["get"],       "route": "recipes"     },     {       "type": "http",       "direction": "out",       "name": "res"     }   ] }

Moreover, we can add parameters to our function’s route by using curly braces: route: recipes/{id}. We can then read the ID parameter in our code from the req object:

const recipeId = req.params.id;

How can I deploy to the cloud?

Congratulations, you’ve made it to the last step! 🎉 Time to push this goodness to the cloud. As always, the VS Code extension has your back. All it really takes is a single right-click we’re pretty much done.

Deployment using VS Code

The extension will ZIP up the code with the Node modules and push them all to the cloud.

While this option is great when testing our own code or maybe when working on a small project, it’s easy to overwrite someone else’s changes by accident — or even worse, your own.

Don’t let friends right-click deploy!
— every DevOps engineer out there

A much healthier option is setting up on GitHub deployment which can be done in a couple of steps in the Azure portal, via the Deployment Center tab.

Github deployment

Are you ready to make Serverless APIs?

This has been a thorough introduction to the world of Servless APIs. However, there’s much, much more than what we’ve covered here. Serverless enables us to solve problems creatively and at a fraction of the cost we usually pay for using traditional platforms.

Chris has mentioned it in other posts here on CSS-Tricks, but he created this excellent website where you can learn more about serverless and find both ideas and resources for things you can build with it. Definitely check it out and let me know if you have other tips or advice scaling with serverless.

The post 7 things you should know when getting started with Serverless APIs appeared first on CSS-Tricks.

CSS-Tricks

, , , , , ,
[Top]

Get Started with Node: An Introduction to APIs, HTTP and ES6+ JavaScript

Jamie Corkhill has written this wonderful post about Node and I think it’s perhaps one of the best technical articles I’ve ever read. Not only is it jam-packed with information for folks like me who aren’t writing JavaScript everyday, it is also incredibly deliberate as Jamie slowly walks through the very basics of JavaScript (such as synchronous and asynchronous functions) all the way up to working with our very own API.

Jamie writes:

What is Node in the first place? What exactly does it mean for Node to be “asynchronous”, and how does that differ from “synchronous”? What is the meaning “event-driven” and “non-blocking” anyway, and how does Node fit into the bigger picture of applications, Internet networks, and servers?

We’ll attempt to answer all of these questions and more throughout this series as we take an in-depth look at the inner workings of Node, learn about the HyperText Transfer Protocol, APIs, and JSON, and build our very own Bookshelf API utilizing MongoDB, Express, Lodash, Mocha, and Handlebars.

I would highly recommend this post if JavaScript isn’t your day job but you’ve always wanted to learn about Node in a bit more detail.

Direct Link to ArticlePermalink

The post Get Started with Node: An Introduction to APIs, HTTP and ES6+ JavaScript appeared first on CSS-Tricks.

CSS-Tricks

, , , , , ,
[Top]