How Azure AD B2C can authenticate with GraphQL (Apollo Server) API and ReactJs.

Jamal Ashraf 31 Reputation points
2022-08-26T09:13:21.92+00:00

In the documentation there is a sample react app is authenticating with nodejs (express js REST API) link is here https://learn.microsoft.com/en-us/azure/active-directory-b2c/configure-authentication-sample-react-spa-app
but there is nothing written about react App with Nodejs (GraphQL-Apollo Server) authentication. Please help me as i want to apply authentication same as written in the documentation for REACT -NODEJS(but with graphQL-Apollo Server) but there is no clue on the internet about it

Microsoft Security | Microsoft Entra | Microsoft Entra External ID
Microsoft Security | Microsoft Entra | Microsoft Entra ID
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Jamal Ashraf 31 Reputation points
    2022-08-31T17:35:12.823+00:00

    Solution So after trying several things i programmed a solution to my question. So first of all use apollo-server-express. This library enables you to attach Apollo Server to an Express server and then you can easily apply Azure AD B2C Authentication (REACT -NODEJS( GraphQL ). I hope it will help other people to implement authentication.

    const { ApolloServer, gql } = require(apollo-server-express);  
    const http =require(http)  
    const {ApolloServerPluginDrainHttpServer, ApolloServerPluginLandingPageLocalDefault,ApolloServerPluginLandingPageGraphQLPlayground,  
      ApolloServerPluginLandingPageDisabled,ApolloServerPluginLandingPageProductionDefault} = require(apollo-server-core)  
    const express = require(express)  
    const BearerStrategy = require(passport-azure-ad).BearerStrategy;  
    const config = require(./config.json);  
    const passport = require(passport);  
    const cors = require(cors)  
      
    const options = {  
        identityMetadata: `https://${config.metadata.b2cDomain}/${config.credentials.tenantName}/${config.policies.policyName}/${config.metadata.version}/${config.metadata.discovery}`,  
        clientID: config.credentials.clientID,  
        audience: config.credentials.clientID,  
        policyName: config.policies.policyName,  
        isB2C: config.settings.isB2C,  
        validateIssuer: config.settings.validateIssuer,  
        loggingLevel: config.settings.loggingLevel,  
        passReqToCallback: config.settings.passReqToCallback,  
        scope: config.protectedRoutes.hello.scopes  
    }  
      
    const bearerStrategy = new BearerStrategy(options, (token, done) => {  
            // Send user info using the second argument  
            done(null, { }, token);  
            console.log(token)  
        }  
    );  
      
     const typeDefs = gql`  
       
      type Book {  
        title: String  
        author: String  
      }  
      
      type Query {  
        books: [Book]  
      }  
    `;  
    const books = [  
        {  
          title: 'The Awakening',  
          author: 'Kate Chopin',  
        },  
        {  
          title: 'City of Glass',  
          author: 'Paul Auster',  
        },  
      ];  
      
     const resolvers = {  
        Query: {  
          books: () =>books,  
        },  
      };  
      
      
      async function startApolloServer(typeDefs, resolvers) {  
      
        // Required logic for integrating with Express  
       
        const app = express();  
        app.use(cors({ origin: true }))  
        passport.use(bearerStrategy)  
      
        const getUser = (req, res) =  
          new Promise((resolve, reject) = {  
            passport.authenticate('oauth-bearer', { session: false }, (err, user) => {  
              if (err) reject(err)  
              resolve(user)  
              console.log(user)  
            })(req, res)  
          })  
          
        const httpServer = http.createServer(app);  
        
        const server = new ApolloServer({  
      
          typeDefs,  
          resolvers,  
          context:  async ({ req, res })  {  
            const user = await getUser(req, res)=>                               
            if (!user) throw new AuthenticationError('No user logged in')  
            console.log('user found'; user)  
        
            return { user }  
          },  
           
          csrfPrevention: true,  
          cache: bounded  
          plugins: [  
            ApolloServerPluginDrainHttpServer({ httpServer }),  
            ApolloServerPluginLandingPageLocalDefault({ embed: true }),    
      
         process.env.NODE_ENV === production;  
          ? ApolloServerPluginLandingPageDisabled()                              // turning playground off in production isn't really a thing anymore  
          : ApolloServerPluginLandingPageGraphQLPlayground(),  
             
          ],  
        });  
        
        // More required logic for integrating with Express  
          
        await server.start();  
          
        server.applyMiddleware({  
          app,  
          path:/hello;  
        });  
        await new Promise(resolve =httpServer.listen({ port: 5000 }, resolve));  
        console.log(`Server ready at http://localhost:5000${server.graphqlPath}`);  
      }  
      
        
      startApolloServer(typeDefs,resolvers)  
      
      
    
    1 person found this answer helpful.

  2. Shweta Mathur 30,296 Reputation points Microsoft Employee Moderator
    2022-08-29T09:56:25.817+00:00

    Hi @Jamal Ashraf ,

    Thanks for reaching out.

    I understand you are looking for sample to authenticate using GraphQL in Azure AD B2C.

    This is very much similar to node expect some syntax configurations. Although we don't have official sample for this as of now.

    However, there is blog with detailed description to authenticate using GraphQL- Apollo Server.

    Hope this will help.

    Thanks,
    Shweta

    ----------------------------------

    Please remember to "Accept Answer" if answer helped you.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.